<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://wiki.mamedev.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aaron</id>
	<title>MAMEDEV Wiki - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.mamedev.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aaron"/>
	<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Special:Contributions/Aaron"/>
	<updated>2026-04-04T13:23:59Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=4009</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=4009"/>
		<updated>2012-09-12T18:35:13Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
Devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
This example is broken into four subsections, describing the configuration structure, the configuration class, the device configuration macros, and then finally the runtime class itself.&lt;br /&gt;
&lt;br /&gt;
==Static Configuration Structure==&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
==Configuration Class==&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
 &lt;br /&gt;
     // internal state&lt;br /&gt;
     int        m_additional_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
* The constructor for the configuration class is kept private. The only way to allocate a new instance of a device configuration is via the static method &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;(). The parameters passed to the constructor in this example are the ones that need to be passed onto the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
Walking through the methods defined in this class one by one, most of them are fairly simple and straightforward. First, the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device_config::example1_device_config(const machine_config &amp;amp;mconfig, const char *tag, &lt;br /&gt;
                 const device_config *owner, UINT32 clock)&lt;br /&gt;
     : device_config(mconfig, static_alloc_device_config, tag, owner, clock),&lt;br /&gt;
       m_additional_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can see, most of the parameters just pass through to the base class. But be sure to initialize all configuration member variables here to ensure they get proper values. We could initialize the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; class here as well, but we&#039;ll wait until the configuration step is complete.&lt;br /&gt;
&lt;br /&gt;
Next up is the static device configuration allocator:&lt;br /&gt;
&lt;br /&gt;
 device_config *example1_device_config::static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
                 const char *tag, const device_config *owner, UINT32 clock)&lt;br /&gt;
 {&lt;br /&gt;
     return global_alloc(example1_device_config(mconfig, tag, owner, clock));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This function is required to be present, as the pointer to this function is used to identify the device type. Given just this function pointer, a configuration object can be constructed, and from there, the device can be created. Note that we need to use &#039;&#039;&#039;global_alloc&#039;&#039;&#039; here because the running_machine has not yet be created (and in fact never may be). Also note that we return a pointer to the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class here, since the machine configuration only knows about the base classes.&lt;br /&gt;
&lt;br /&gt;
The device allocator function follows, and it is also required:&lt;br /&gt;
&lt;br /&gt;
 device_t *example1_device_config::alloc_device(running_machine &amp;amp;machine) const&lt;br /&gt;
 {&lt;br /&gt;
     return auto_alloc(&amp;amp;machine, example1_device(machine, *this));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In contrast to the configuration allocator, which is static and uses &#039;&#039;&#039;global_alloc&#039;&#039;&#039;, the device allocator is a virtual method that uses &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; in order to allocate the device and assign its memory to the provided running machine. When we construct the actual device object, we pass the machine through along with a reference to ourself so that the newly created device can have access to our configuration information.&lt;br /&gt;
&lt;br /&gt;
Once all the device configurations have been created and populated, the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method is called. We override it here to set up our inherited copy of the static configuration structure:&lt;br /&gt;
&lt;br /&gt;
 void example1_device_config::device_config_complete()&lt;br /&gt;
 {&lt;br /&gt;
     // copy static configuration if present&lt;br /&gt;
     if (m_static_config != NULL)&lt;br /&gt;
         *static_cast&amp;lt;example1_device_config_data *&amp;gt;(this) =&lt;br /&gt;
                        *reinterpret_cast&amp;lt;const example1_device_config_data *&amp;gt;(m_static_config);&lt;br /&gt;
 &lt;br /&gt;
     // otherwise, initialize it to defaults&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         m_device_integer_data = DEFAULT_INT_VALUE;&lt;br /&gt;
         m_device_string_data = NULL;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the case where the user specified a pointer to a static configuration data structure, we copy it into ourselves. We use static_cast to find the pointer to where the inherited state lives within our structure and then copy the data pointed to by &#039;&#039;&#039;m_static_config&#039;&#039;&#039;. If no configuration data was provided, we take this opportunity to initialize the inherited configuration structure to default values.&lt;br /&gt;
&lt;br /&gt;
Finally, if the device wishes to provide stronger validation of data -- verified both when starting a game as well as when running MAME with the -validate option -- it can ovverride the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039; method:&lt;br /&gt;
&lt;br /&gt;
 bool example1_device_config::device_validity_check(const game_driver &amp;amp;driver) const&lt;br /&gt;
 {&lt;br /&gt;
     bool error = false;&lt;br /&gt;
 &lt;br /&gt;
     // sanity check configuration&lt;br /&gt;
     if (m_device_integer_value &amp;lt; 0)&lt;br /&gt;
     {&lt;br /&gt;
          mame_printf_error(&amp;quot;%s: %s device &#039;%s&#039; has invalid integer parameter\n&amp;quot;, &lt;br /&gt;
                            driver.source_file, driver.name, tag());&lt;br /&gt;
          error = true;&lt;br /&gt;
     }&lt;br /&gt;
     return error;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method should examing the configuration data, output friendly errors and warnings, and return true if a fatal error was detected.&lt;br /&gt;
&lt;br /&gt;
==Configuration Macros==&lt;br /&gt;
&lt;br /&gt;
Now we need to declare how to reference the device from a machine configuration. This is done via special tokenizing macros:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_ADD(&amp;quot;tag&amp;quot;, DEVICE_TYPE, device_clock)&lt;br /&gt;
 MDRV_DEVICE_REPLACE(&amp;quot;tag&amp;quot;, DEVICE_TYPE, device_clock)&lt;br /&gt;
&lt;br /&gt;
So the first thing we need to define is our ALL_CAPS DEVICE_TYPE. As mentioned previously, the device type is simply a pointer to the static &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;() method, so it should be defined like so:&lt;br /&gt;
&lt;br /&gt;
 static const device_type EXAMPLE1 = example1_device_config::static_alloc_device_config;&lt;br /&gt;
&lt;br /&gt;
Although this is all that is required at a minimum, in general it is considered a good idea to provide your own set of MDRV macros that are specific to your device. By defining our macros, we can more precisely guide the user to ensure all data is properly specified. Let&#039;s say for example that our static configuration is required (i.e., it is invalid to not specify anything). Using the raw macros, a driver writer would declare an instance of our device like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_ADD(&amp;quot;tag&amp;quot;, EXAMPLE1, 0)&lt;br /&gt;
 MDRV_DEVICE_CONFIG(local_structure)&lt;br /&gt;
&lt;br /&gt;
Given this, you can see that it would be easy to forget the second line and leave a device with no configuration data. Also, the user is forced to specify a dummy clock, even though our device doesn&#039;t need one. Instead, let&#039;s define our own macro for adding an EXAMPLE1 device, like so:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_EXAMPLE1_ADD(_tag, _config) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, EXAMPLE1, 0) \&lt;br /&gt;
     MDRV_DEVICE_CONFIG(_config)&lt;br /&gt;
&lt;br /&gt;
and then the equivalent declaration becomes:&lt;br /&gt;
&lt;br /&gt;
 MDRV_EXAMPLE1_ADD(&amp;quot;tag&amp;quot;, local_structure)&lt;br /&gt;
&lt;br /&gt;
By doing this, we get to provide a cleaner interface for declaration, and at the same time we ensure that a required parameter is specified.&lt;br /&gt;
&lt;br /&gt;
==Runtime Class==&lt;br /&gt;
&lt;br /&gt;
Next we move on to the runtime device class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device : public device_t&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device_config;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device(running_machine &amp;amp;machine, const example1_device_config &amp;amp;config);&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // any publically acessible interfaces needed for runtime&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides (none are required, but these are common)&lt;br /&gt;
     virtual void device_start();&lt;br /&gt;
     virtual void device_reset();&lt;br /&gt;
 &lt;br /&gt;
     // internal device state goes here&lt;br /&gt;
     const example1_device_config &amp;amp;m_config;&lt;br /&gt;
     int                           m_device_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Going through the class definition, there are some similar patterns to the corresponding device configuration class:&lt;br /&gt;
&lt;br /&gt;
* Again, we derive from a common base class, in this case the &#039;&#039;&#039;device_t&#039;&#039;&#039; class. However, unlike the configuration class, we just have simple single inheritance here, since we don&#039;t need the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct.&lt;br /&gt;
&lt;br /&gt;
* We make our configuration class our friend, just as they made us their friend. Really, you should imagine these two classes as two halves of the entire device.&lt;br /&gt;
&lt;br /&gt;
* As with the configuration class, our constructor is kept private. A device should only be allocated via the corresponding configuration class&#039;s &#039;&#039;&#039;alloc_device&#039;&#039;&#039;() method. Since our configuration class is our friend, it can still allocate us.&lt;br /&gt;
&lt;br /&gt;
* There are no standard methods that need to be public in the runtime device. However, it is quite likely you will need some in order to interact with it (read/write handlers fall into this category, for example).&lt;br /&gt;
&lt;br /&gt;
* This example overrides two device-specific notification methods, one which is called at device start time (after all devices are constructed), and one which is called at reset time. These are optional, though common, to override.&lt;br /&gt;
&lt;br /&gt;
* At the bottom you&#039;ll see a reference to our configuration class. This is kept to enable easy access to the configuration data.&lt;br /&gt;
&lt;br /&gt;
Looking at each of the methods above in a little detail, we first encounter the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device::example1_device(running_machine &amp;amp;machine, const example1_device_config &amp;amp;config)&lt;br /&gt;
     : device_t(machine, config),&lt;br /&gt;
       m_config(config),&lt;br /&gt;
       m_device_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Here we initialize our parent class by passing down the reference to the running_machine and our configuration. We also stash a reference to our configuration into the m_config variable for later use, and we reset all our internal state variables to something well-defined. Note that we don&#039;t generally do much initialization in the constructor; that work is preferred to live in the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Speaking of which...&lt;br /&gt;
&lt;br /&gt;
 example1_device::device_start()&lt;br /&gt;
 {&lt;br /&gt;
     // initialize state from configuration&lt;br /&gt;
     // locate any other devices&lt;br /&gt;
     //    if other devices not ready, throw device_missing_dependencies()&lt;br /&gt;
     // register for any save state&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Okay, not much meat in the implementation above, but there are a number of things expected of a device during &#039;&#039;&#039;device_start&#039;&#039;&#039;() time, including consumption of the configuration, identification of related devices, and set up for save states. If a related device is located (at this point all devices are constructed) but it hasn&#039;t yet been started, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039;() exception and your &#039;&#039;&#039;device_start&#039;&#039;&#039;() will be queued to the end of the list to be called again later.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
 example1_device::device_reset()&lt;br /&gt;
 {&lt;br /&gt;
     // reset internal state to well-defined values&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method is there to enable resetting a device&#039;s state in the event of a requested reset.&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=4008</id>
		<title>MAME Coding Conventions</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=4008"/>
		<updated>2012-09-12T18:31:56Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is WIP. Please don&#039;t edit it until this notice is removed.&lt;br /&gt;
&lt;br /&gt;
MAME is a project that has had many contributors from many different backgrounds. Throughout its history, there have never really been any kind of formal coding conventions defined, although thanks to imitation, there is at least a glimmer of consistency.&lt;br /&gt;
&lt;br /&gt;
In general, a codebase with consistent conventions is easier to understand than one with varying conventions. However, trying to impose a strict order on a project of this magnitude is certainly taking things too far.&lt;br /&gt;
&lt;br /&gt;
If you categorize the MAME codebase, you can look at it like this:&lt;br /&gt;
* OS-specific code (OSD)&lt;br /&gt;
* MAME &amp;quot;core&amp;quot; code&lt;br /&gt;
* CPU cores&lt;br /&gt;
* Sound engines&lt;br /&gt;
* Game drivers&lt;br /&gt;
&lt;br /&gt;
The first two pieces (the core and OSD) are in general only handled by a small group of developers, while the remaining pieces (drivers and CPU/sound cores) come from a much broader audience. Furthermore, the drivers and CPU/sound cores all interact to some degree with core and OSD pieces below them, so the most benefit from code clarity and consistency comes from making the core and OSD pieces consistent.&lt;br /&gt;
&lt;br /&gt;
With that in mind, below is an outline some of the key coding conventions currently in use in the core and OSD layers. If you are modifying code in these layers and wish to have it accepted upon submission, you would do well to keep to these guidelines. (In fact, if you are modifying any file in any project, you should adopt the conventions of that file/project, rather than just stuffing your own inconsistent style in the middle of something else. I can&#039;t believe how many people just ignore the existing styles and jam their own style in the middle.)&lt;br /&gt;
&lt;br /&gt;
One more thing. Keep in mind that coding conventions are like religion: they are often strongly-held beliefs with little factual justification to back them up. You may disagree with them. Heck, even I disagree with a few of them. But they are the conventions that are used. Deal with it.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
* function, method, and variable names are named using the &amp;lt;code&amp;gt;lower_under_convention&amp;lt;/code&amp;gt;&lt;br /&gt;
* static member functions should have a static_ prefix (e.g., &amp;lt;code&amp;gt;static_timer_callback&amp;lt;/code&amp;gt;)&lt;br /&gt;
* member variables within a class should have a standard prefix, as follows:&lt;br /&gt;
** normal variables should have an m_ prefix (e.g., &amp;lt;code&amp;gt;m_device&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;m_config&amp;lt;/code&amp;gt;, etc)&lt;br /&gt;
** static members should have an s_ prefix (e.g., &amp;lt;code&amp;gt;s_device_table&amp;lt;/code&amp;gt;)&lt;br /&gt;
** static constant members should be treated as constants and should be in ALL_CAPS_UNDER_FORMAT (e.g., &amp;lt;code&amp;gt;MAXIMUM_ITEMS&amp;lt;/code&amp;gt;)&lt;br /&gt;
* macros, enum items, and #defined constants should be named using the &amp;lt;code&amp;gt;ALL_CAPS_UNDER_CONVENTION&amp;lt;/code&amp;gt;&lt;br /&gt;
* constants which are part of a group should have a common prefix; example: &amp;lt;code&amp;gt;enum { ADDRESS_SPACE_PROGRAM, ADDRESS_SPACE_DATA, ADDRESS_SPACE_IO };&amp;lt;/code&amp;gt;&lt;br /&gt;
* prefer descriptive variable names (&amp;lt;code&amp;gt;sampnum&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memoffset&amp;lt;/code&amp;gt;) over single-letter names (&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;j&amp;lt;/code&amp;gt;)&lt;br /&gt;
* never use the prefix &amp;quot;my&amp;quot; for anything; it&#039;s not &amp;quot;myobject&amp;quot;, just use &amp;quot;object&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
* comments in the code are preferred to be &amp;lt;code&amp;gt;// C++-style comments&amp;lt;/code&amp;gt;, though &amp;lt;code&amp;gt;/* standard C-style comments */&amp;lt;/code&amp;gt; are still very common&lt;br /&gt;
* each function should have a comment preceding it that briefly describes what that function does&lt;br /&gt;
* each file should begin with a header that includes information about the licensing of that file; if no licensing information is given, the standard MAME license is assumed&lt;br /&gt;
&lt;br /&gt;
== Spacing ==&lt;br /&gt;
* a space should be used between binary and trinary operators &amp;amp;mdash; example: &amp;lt;code&amp;gt;a + b / 2&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used around parentheses in expressions &amp;amp;mdash; example: &amp;lt;code&amp;gt;(((i + j) * k) &amp;gt;&amp;gt; m)&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used between a function and its parameters &amp;amp;mdash; example: &amp;lt;code&amp;gt;function(param1, param2)&amp;lt;/code&amp;gt;&lt;br /&gt;
* a space should be used between keywords (if, while, for) and their arguments &amp;amp;mdash; example: &amp;lt;code&amp;gt;for (x = 0; x &amp;lt; 10; x++)&amp;lt;/code&amp;gt;&lt;br /&gt;
* opening/closing braces should be on their own line, and should be indented to align with the start of the statement that introduces them&lt;br /&gt;
* two blank lines should separate the end of a function from the start of the next function&lt;br /&gt;
&lt;br /&gt;
== Expressions ==&lt;br /&gt;
* do not use parentheses with &#039;&#039;&#039;return&#039;&#039;&#039;, it is not a function &amp;amp;mdash; example: &amp;lt;code&amp;gt;return 0;&amp;lt;/code&amp;gt;&lt;br /&gt;
* do not overuse parentheses except to clarify a statement &amp;amp;mdash; example: &amp;lt;code&amp;gt;if (a &amp;gt;= 10 &amp;amp;&amp;amp; a &amp;lt; 20)&amp;lt;/code&amp;gt;&lt;br /&gt;
* always use NULL (not 0) when working with pointers&lt;br /&gt;
* make comparisons against NULL explicit: &amp;lt;code&amp;gt;if (ptr != NULL)&amp;lt;/code&amp;gt;&lt;br /&gt;
* make comparisons against 0 explicit: &amp;lt;code&amp;gt;if (strcmp(string1, string2) == 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;don&#039;t&#039;&#039; make comparisons against boolean values explicit: &amp;lt;code&amp;gt;val = (a == b); if (val)...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Language conventions ==&lt;br /&gt;
* prefer references over pointers, using pointers primarily in situations where NULL is a valid option&lt;br /&gt;
* use &#039;&#039;&#039;static&#039;&#039;&#039; and &#039;&#039;&#039;const&#039;&#039;&#039; keywords aggressively where appropriate&lt;br /&gt;
* create typedefs for function pointers; example: &amp;lt;code&amp;gt;typedef void (*my_callback_func)(UINT32 param);&amp;lt;/code&amp;gt;&lt;br /&gt;
* make calls through function pointers explicit &amp;amp;mdash; example: &amp;lt;code&amp;gt;(*funcptr)(a, b)&amp;lt;/code&amp;gt;&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;enum&#039;&#039;&#039; instead of a macro&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;inline&#039;&#039;&#039; functions instead of macros&lt;br /&gt;
* wherever possible, use templates instead of macros&lt;br /&gt;
* macros that look like functions should be wrapped with &amp;lt;code&amp;gt;do { &amp;amp;lt;macrobody&amp;amp;gt; } while (0)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
* avoid declaring static variables inside a function scope &amp;amp;mdash; these are really global variables and belong at the top of the module&lt;br /&gt;
* declare all global variables at the top of the file&lt;br /&gt;
* use the MAME-defined types: &amp;lt;code&amp;gt;INT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT64&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Header Files ==&lt;br /&gt;
* the preferred order of definitions in a header file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** reinclusion protection (see below)&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables&lt;br /&gt;
** function prototypes&lt;br /&gt;
** and inline functions&lt;br /&gt;
* function prototypes in header files generally do not use an &#039;&#039;&#039;extern&#039;&#039;&#039; qualifier&lt;br /&gt;
* all header files should support reinclusion; this is done by adding the following to the top of each header&lt;br /&gt;
 #pragma once&lt;br /&gt;
 &lt;br /&gt;
 #ifndef __FILENAME_H__&lt;br /&gt;
 #define __FILENAME_H__&lt;br /&gt;
and adding&lt;br /&gt;
 #endif /* __FILENAME__H__ */&lt;br /&gt;
to the end. Note that &amp;lt;code&amp;gt;#pragma once&amp;lt;/code&amp;gt; is provided because it is generally faster when supported. Since not all compilers do support it, the &amp;lt;code&amp;gt;#ifndef/#define&amp;lt;/code&amp;gt; methods are retained as a fallback.&lt;br /&gt;
&lt;br /&gt;
== Source Files ==&lt;br /&gt;
* the preferred order of code in a source file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables (both static and global)&lt;br /&gt;
** internal function prototypes&lt;br /&gt;
** inline functions&lt;br /&gt;
** externally referenced functions&lt;br /&gt;
** internal functions (in same order as prototyped)&lt;br /&gt;
&lt;br /&gt;
Back to [[How MAME Works]]&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Submitting_Source_Code&amp;diff=4007</id>
		<title>Submitting Source Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Submitting_Source_Code&amp;diff=4007"/>
		<updated>2012-09-12T18:31:44Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you&#039;re handy with C and want to help out, there are several ways you can do so. Source code submissions from outside developers are welcome. In fact, many of the more unexpected improvements to MAME come from folks who are not &amp;quot;official&amp;quot; MAME devs. &lt;br /&gt;
&lt;br /&gt;
== Acceptable Submissions ==&lt;br /&gt;
&lt;br /&gt;
When working on modifications to MAME, keep the following guidelines in mind: &lt;br /&gt;
&lt;br /&gt;
* We are not interested in adding features to MAME to make games look better or improve playability or cheat the hardware emulation in order to make things run faster. Submissions that serve only to do this will not be considered. &lt;br /&gt;
* Technical accuracy is our #1 goal. ROM patches or hacks to games are generally not appropriate as they do not improve our understanding of the hardware. Submissions which are merely wild guesses about something and which don&#039;t make sense based on what is known about the hardware will tend to be rejected. &lt;br /&gt;
* ROM set naming in MAME is arbitrary. There is no point in submitting changes to ROM set names; they are crammed into 8 characters and have many other limitations. Plus it tends to annoy the developers. &lt;br /&gt;
* If you think there is a problem in the naming of a game, you should [http://mamedev.org/contact.html?team send an email] rather than a source code patch. Game names changes are discussed among the developers and aren&#039;t really code changes. &lt;br /&gt;
* Cosmetic changes to the source are best left up to the core developers. If your change doesn&#039;t add anything worthwhile to the actual code, it is not worth your time to submit it. &lt;br /&gt;
&lt;br /&gt;
== Submission Guidelines ==&lt;br /&gt;
&lt;br /&gt;
Before sending in a submission, you should make sure that you follow these guidelines: &lt;br /&gt;
&lt;br /&gt;
* All submissions must be compiled in both debug (make DEBUG=1) and non-debug builds using the official build tools ([http://mamedev.org/tools download them from here]), and all warnings or errors fixed. &lt;br /&gt;
* All submissions should be in diff format, taken against the [http://mamedev.org/updates.html most recent intermediate update]. (If you are using Windows, you can get a set of diff/patch tools [http://mamedev.org/tools/diffpatch-mingw.exe here].) &lt;br /&gt;
* To create a correct diff, use the following command line: &lt;br /&gt;
 diff -Nru originaltree modifiedtree &amp;gt;patchname.diff &lt;br /&gt;
where originaltree is the &#039;src&#039; directory of the original, unmodified sources; modifiedtree is the &#039;src&#039; directory of your updated sources; and patchname.diff is the name of the diff you want to create. &lt;br /&gt;
* Once you have a .diff containing your changes, ZIP it up and submit it by sending email to [[image:Submit-email.png|frameless|122x12px|baseline]]. &lt;br /&gt;
&lt;br /&gt;
Submissions are most often accepted or rejected without feedback. If you submitted something and it hasn&#039;t shown up in MAME within a few intermediate releases, feel free to ask what the status of your submission is.&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
&lt;br /&gt;
MAME is a huge project, and to work on many parts of it requires extensive understanding of C, arcade game hardware, CPU architectures, audio systems, graphics systems, and reverse engineering. These are not easy to come by, and the learning curve is very steep. That said, there are still ways of contributing to MAME that don&#039;t require a full top-to-bottom understanding of everything. Here are a couple of suggestions: &lt;br /&gt;
&lt;br /&gt;
# Add save state support to a driver. The save state system is very modular and pretty straightforward to use. Furthermore, very few drivers are set up to use it right now. Digging into a driver and figuring out what data needs to be preserved in order to resume execution is a great way to learn about MAME. &lt;br /&gt;
# Figure out what unknown DIP switches do. Some of this can be determined by twiddling the DIP switches and watching what happens, but often this is not enough. Delving into the game code to understand how the DIP switches are read and what their values are used for is a good beginning challenge in reverse engineering. &lt;br /&gt;
# Go to [http://www.mametesters.org/ MAMETesters] and look over the bugs. There are many tricky bugs in there, but there are also many straightforward issues that nobody has yet taken the time to look into. &lt;br /&gt;
&lt;br /&gt;
If you&#039;re new to emulator programming, these are a far better places to start than trying to tackle the emulation of a game that doesn&#039;t yet work. Any games that still don&#039;t work are usually due to complicated protection or hardware emulation issues and are more than likely going to be a daunting (and discouraging) challenge for someone just getting started.&lt;br /&gt;
&lt;br /&gt;
Back to [[How MAME Works]]&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Contributing_to_MAME&amp;diff=4006</id>
		<title>Contributing to MAME</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Contributing_to_MAME&amp;diff=4006"/>
		<updated>2012-09-12T18:31:33Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MAME is strictly a not-for-profit project that has been written with the help of hundreds of people around the world. Contributions are always welcome in the form of testing, technical information, and source code submissions. &lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
Probably the easiest way to help out is to test the games in MAME. Many developers are not particularly strong game players, and quite often have not thoroughly tested a game from beginning to end looking for issues. If you are playing a game and notice something wrong, please report bugs to [http://mametesters.org MAMETesters]. Make sure you are running the most recent intermediate update and are only using the official command-line version of MAME before submitting reports. &lt;br /&gt;
&lt;br /&gt;
== Technical Information ==&lt;br /&gt;
If you are the owner of one or more games or game PCBs and are interested in helping out, there are several ways you can do so: &lt;br /&gt;
&lt;br /&gt;
* You can run MAME side-by-side with your PCB to look for graphics, sound, or gameplay issues. If you find any issues, please report them to MAMETesters. &lt;br /&gt;
* You can make detailed notes of all the components on your PCB, including part numbers, locations, and labels. This information can then be added to the source code for future reference. &lt;br /&gt;
* If you have an EPROM programmer, you can read the ROMs from your PCB to see if they are a match for what is currently supported in MAME, or if they are an alternate revision. Use mame -romident to identify ROM images that are dumped. &lt;br /&gt;
* If you own a PCB for a game that doesn&#039;t currently work in MAME, let us know, especially if you have an EPROM programmer. We can potentially work with you by asking you to run tests on the game to help us get it up and running. &lt;br /&gt;
&lt;br /&gt;
== Source Code Submissions ==&lt;br /&gt;
If you&#039;re handy with C and want to help out, there are several ways you can do so. Source code submissions from outside developers are welcome. In fact, many of the more unexpected improvements to MAME come from folks who are not &amp;quot;official&amp;quot; MAME devs. &lt;br /&gt;
&lt;br /&gt;
There is a whole page dedicated to how to submit source code changes to MAME. [[Submitting Source Code|Check it out.]]&lt;br /&gt;
&lt;br /&gt;
Back to [[How MAME Works]]&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=4005</id>
		<title>MAME Coding Conventions</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=4005"/>
		<updated>2012-09-12T18:29:06Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Naming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is WIP. Please don&#039;t edit it until this notice is removed.&lt;br /&gt;
&lt;br /&gt;
MAME is a project that has had many contributors from many different backgrounds. Throughout its history, there have never really been any kind of formal coding conventions defined, although thanks to imitation, there is at least a glimmer of consistency.&lt;br /&gt;
&lt;br /&gt;
In general, a codebase with consistent conventions is easier to understand than one with varying conventions. However, trying to impose a strict order on a project of this magnitude is certainly taking things too far.&lt;br /&gt;
&lt;br /&gt;
If you categorize the MAME codebase, you can look at it like this:&lt;br /&gt;
* OS-specific code (OSD)&lt;br /&gt;
* MAME &amp;quot;core&amp;quot; code&lt;br /&gt;
* CPU cores&lt;br /&gt;
* Sound engines&lt;br /&gt;
* Game drivers&lt;br /&gt;
&lt;br /&gt;
The first two pieces (the core and OSD) are in general only handled by a small group of developers, while the remaining pieces (drivers and CPU/sound cores) come from a much broader audience. Furthermore, the drivers and CPU/sound cores all interact to some degree with core and OSD pieces below them, so the most benefit from code clarity and consistency comes from making the core and OSD pieces consistent.&lt;br /&gt;
&lt;br /&gt;
With that in mind, below is an outline some of the key coding conventions currently in use in the core and OSD layers. If you are modifying code in these layers and wish to have it accepted upon submission, you would do well to keep to these guidelines. (In fact, if you are modifying any file in any project, you should adopt the conventions of that file/project, rather than just stuffing your own inconsistent style in the middle of something else. I can&#039;t believe how many people just ignore the existing styles and jam their own style in the middle.)&lt;br /&gt;
&lt;br /&gt;
One more thing. Keep in mind that coding conventions are like religion: they are often strongly-held beliefs with little factual justification to back them up. You may disagree with them. Heck, even I disagree with a few of them. But they are the conventions that are used. Deal with it.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
* function, method, and variable names are named using the &amp;lt;code&amp;gt;lower_under_convention&amp;lt;/code&amp;gt;&lt;br /&gt;
* static member functions should have a static_ prefix (e.g., &amp;lt;code&amp;gt;static_timer_callback&amp;lt;/code&amp;gt;)&lt;br /&gt;
* member variables within a class should have a standard prefix, as follows:&lt;br /&gt;
** normal variables should have an m_ prefix (e.g., &amp;lt;code&amp;gt;m_device&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;m_config&amp;lt;/code&amp;gt;, etc)&lt;br /&gt;
** static members should have an s_ prefix (e.g., &amp;lt;code&amp;gt;s_device_table&amp;lt;/code&amp;gt;)&lt;br /&gt;
** static constant members should be treated as constants and should be in ALL_CAPS_UNDER_FORMAT (e.g., &amp;lt;code&amp;gt;MAXIMUM_ITEMS&amp;lt;/code&amp;gt;)&lt;br /&gt;
* macros, enum items, and #defined constants should be named using the &amp;lt;code&amp;gt;ALL_CAPS_UNDER_CONVENTION&amp;lt;/code&amp;gt;&lt;br /&gt;
* constants which are part of a group should have a common prefix; example: &amp;lt;code&amp;gt;enum { ADDRESS_SPACE_PROGRAM, ADDRESS_SPACE_DATA, ADDRESS_SPACE_IO };&amp;lt;/code&amp;gt;&lt;br /&gt;
* prefer descriptive variable names (&amp;lt;code&amp;gt;sampnum&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memoffset&amp;lt;/code&amp;gt;) over single-letter names (&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;j&amp;lt;/code&amp;gt;)&lt;br /&gt;
* never use the prefix &amp;quot;my&amp;quot; for anything; it&#039;s not &amp;quot;myobject&amp;quot;, just use &amp;quot;object&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
* comments in the code are preferred to be &amp;lt;code&amp;gt;// C++-style comments&amp;lt;/code&amp;gt;, though &amp;lt;code&amp;gt;/* standard C-style comments */&amp;lt;/code&amp;gt; are still very common&lt;br /&gt;
* each function should have a comment preceding it that briefly describes what that function does&lt;br /&gt;
* each file should begin with a header that includes information about the licensing of that file; if no licensing information is given, the standard MAME license is assumed&lt;br /&gt;
&lt;br /&gt;
== Spacing ==&lt;br /&gt;
* a space should be used between binary and trinary operators &amp;amp;mdash; example: &amp;lt;code&amp;gt;a + b / 2&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used around parentheses in expressions &amp;amp;mdash; example: &amp;lt;code&amp;gt;(((i + j) * k) &amp;gt;&amp;gt; m)&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used between a function and its parameters &amp;amp;mdash; example: &amp;lt;code&amp;gt;function(param1, param2)&amp;lt;/code&amp;gt;&lt;br /&gt;
* a space should be used between keywords (if, while, for) and their arguments &amp;amp;mdash; example: &amp;lt;code&amp;gt;for (x = 0; x &amp;lt; 10; x++)&amp;lt;/code&amp;gt;&lt;br /&gt;
* opening/closing braces should be on their own line, and should be indented to align with the start of the statement that introduces them&lt;br /&gt;
* two blank lines should separate the end of a function from the start of the next function&lt;br /&gt;
&lt;br /&gt;
== Expressions ==&lt;br /&gt;
* do not use parentheses with &#039;&#039;&#039;return&#039;&#039;&#039;, it is not a function &amp;amp;mdash; example: &amp;lt;code&amp;gt;return 0;&amp;lt;/code&amp;gt;&lt;br /&gt;
* do not overuse parentheses except to clarify a statement &amp;amp;mdash; example: &amp;lt;code&amp;gt;if (a &amp;gt;= 10 &amp;amp;&amp;amp; a &amp;lt; 20)&amp;lt;/code&amp;gt;&lt;br /&gt;
* always use NULL (not 0) when working with pointers&lt;br /&gt;
* make comparisons against NULL explicit: &amp;lt;code&amp;gt;if (ptr != NULL)&amp;lt;/code&amp;gt;&lt;br /&gt;
* make comparisons against 0 explicit: &amp;lt;code&amp;gt;if (strcmp(string1, string2) == 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;don&#039;t&#039;&#039; make comparisons against boolean values explicit: &amp;lt;code&amp;gt;val = (a == b); if (val)...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Language conventions ==&lt;br /&gt;
* prefer references over pointers, using pointers primarily in situations where NULL is a valid option&lt;br /&gt;
* use &#039;&#039;&#039;static&#039;&#039;&#039; and &#039;&#039;&#039;const&#039;&#039;&#039; keywords aggressively where appropriate&lt;br /&gt;
* create typedefs for function pointers; example: &amp;lt;code&amp;gt;typedef void (*my_callback_func)(UINT32 param);&amp;lt;/code&amp;gt;&lt;br /&gt;
* make calls through function pointers explicit &amp;amp;mdash; example: &amp;lt;code&amp;gt;(*funcptr)(a, b)&amp;lt;/code&amp;gt;&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;enum&#039;&#039;&#039; instead of a macro&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;inline&#039;&#039;&#039; functions instead of macros&lt;br /&gt;
* wherever possible, use templates instead of macros&lt;br /&gt;
* macros that look like functions should be wrapped with &amp;lt;code&amp;gt;do { &amp;amp;lt;macrobody&amp;amp;gt; } while (0)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
* avoid declaring static variables inside a function scope &amp;amp;mdash; these are really global variables and belong at the top of the module&lt;br /&gt;
* declare all global variables at the top of the file&lt;br /&gt;
* use the MAME-defined types: &amp;lt;code&amp;gt;INT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT64&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Header Files ==&lt;br /&gt;
* the preferred order of definitions in a header file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** reinclusion protection (see below)&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables&lt;br /&gt;
** function prototypes&lt;br /&gt;
** and inline functions&lt;br /&gt;
* function prototypes in header files generally do not use an &#039;&#039;&#039;extern&#039;&#039;&#039; qualifier&lt;br /&gt;
* all header files should support reinclusion; this is done by adding the following to the top of each header&lt;br /&gt;
 #pragma once&lt;br /&gt;
 &lt;br /&gt;
 #ifndef __FILENAME_H__&lt;br /&gt;
 #define __FILENAME_H__&lt;br /&gt;
and adding&lt;br /&gt;
 #endif /* __FILENAME__H__ */&lt;br /&gt;
to the end. Note that &amp;lt;code&amp;gt;#pragma once&amp;lt;/code&amp;gt; is provided because it is generally faster when supported. Since not all compilers do support it, the &amp;lt;code&amp;gt;#ifndef/#define&amp;lt;/code&amp;gt; methods are retained as a fallback.&lt;br /&gt;
&lt;br /&gt;
== Source Files ==&lt;br /&gt;
* the preferred order of code in a source file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables (both static and global)&lt;br /&gt;
** internal function prototypes&lt;br /&gt;
** inline functions&lt;br /&gt;
** externally referenced functions&lt;br /&gt;
** internal functions (in same order as prototyped)&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Submitting_Source_Code&amp;diff=4004</id>
		<title>Submitting Source Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Submitting_Source_Code&amp;diff=4004"/>
		<updated>2012-09-12T18:26:20Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Submission Guidelines */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you&#039;re handy with C and want to help out, there are several ways you can do so. Source code submissions from outside developers are welcome. In fact, many of the more unexpected improvements to MAME come from folks who are not &amp;quot;official&amp;quot; MAME devs. &lt;br /&gt;
&lt;br /&gt;
== Acceptable Submissions ==&lt;br /&gt;
&lt;br /&gt;
When working on modifications to MAME, keep the following guidelines in mind: &lt;br /&gt;
&lt;br /&gt;
* We are not interested in adding features to MAME to make games look better or improve playability or cheat the hardware emulation in order to make things run faster. Submissions that serve only to do this will not be considered. &lt;br /&gt;
* Technical accuracy is our #1 goal. ROM patches or hacks to games are generally not appropriate as they do not improve our understanding of the hardware. Submissions which are merely wild guesses about something and which don&#039;t make sense based on what is known about the hardware will tend to be rejected. &lt;br /&gt;
* ROM set naming in MAME is arbitrary. There is no point in submitting changes to ROM set names; they are crammed into 8 characters and have many other limitations. Plus it tends to annoy the developers. &lt;br /&gt;
* If you think there is a problem in the naming of a game, you should [http://mamedev.org/contact.html?team send an email] rather than a source code patch. Game names changes are discussed among the developers and aren&#039;t really code changes. &lt;br /&gt;
* Cosmetic changes to the source are best left up to the core developers. If your change doesn&#039;t add anything worthwhile to the actual code, it is not worth your time to submit it. &lt;br /&gt;
&lt;br /&gt;
== Submission Guidelines ==&lt;br /&gt;
&lt;br /&gt;
Before sending in a submission, you should make sure that you follow these guidelines: &lt;br /&gt;
&lt;br /&gt;
* All submissions must be compiled in both debug (make DEBUG=1) and non-debug builds using the official build tools ([http://mamedev.org/tools download them from here]), and all warnings or errors fixed. &lt;br /&gt;
* All submissions should be in diff format, taken against the [http://mamedev.org/updates.html most recent intermediate update]. (If you are using Windows, you can get a set of diff/patch tools [http://mamedev.org/tools/diffpatch-mingw.exe here].) &lt;br /&gt;
* To create a correct diff, use the following command line: &lt;br /&gt;
 diff -Nru originaltree modifiedtree &amp;gt;patchname.diff &lt;br /&gt;
where originaltree is the &#039;src&#039; directory of the original, unmodified sources; modifiedtree is the &#039;src&#039; directory of your updated sources; and patchname.diff is the name of the diff you want to create. &lt;br /&gt;
* Once you have a .diff containing your changes, ZIP it up and submit it by sending email to [[image:Submit-email.png|frameless|122x12px|baseline]]. &lt;br /&gt;
&lt;br /&gt;
Submissions are most often accepted or rejected without feedback. If you submitted something and it hasn&#039;t shown up in MAME within a few intermediate releases, feel free to ask what the status of your submission is.&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
&lt;br /&gt;
MAME is a huge project, and to work on many parts of it requires extensive understanding of C, arcade game hardware, CPU architectures, audio systems, graphics systems, and reverse engineering. These are not easy to come by, and the learning curve is very steep. That said, there are still ways of contributing to MAME that don&#039;t require a full top-to-bottom understanding of everything. Here are a couple of suggestions: &lt;br /&gt;
&lt;br /&gt;
# Add save state support to a driver. The save state system is very modular and pretty straightforward to use. Furthermore, very few drivers are set up to use it right now. Digging into a driver and figuring out what data needs to be preserved in order to resume execution is a great way to learn about MAME. &lt;br /&gt;
# Figure out what unknown DIP switches do. Some of this can be determined by twiddling the DIP switches and watching what happens, but often this is not enough. Delving into the game code to understand how the DIP switches are read and what their values are used for is a good beginning challenge in reverse engineering. &lt;br /&gt;
# Go to [http://www.mametesters.org/ MAMETesters] and look over the bugs. There are many tricky bugs in there, but there are also many straightforward issues that nobody has yet taken the time to look into. &lt;br /&gt;
&lt;br /&gt;
If you&#039;re new to emulator programming, these are a far better places to start than trying to tackle the emulation of a game that doesn&#039;t yet work. Any games that still don&#039;t work are usually due to complicated protection or hardware emulation issues and are more than likely going to be a daunting (and discouraging) challenge for someone just getting started.&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Building_MAME_using_Microsoft_Visual_Studio_compilers&amp;diff=4003</id>
		<title>Building MAME using Microsoft Visual Studio compilers</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Building_MAME_using_Microsoft_Visual_Studio_compilers&amp;diff=4003"/>
		<updated>2012-09-12T18:23:31Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;By default, MAME is configured via the makefile to build using the MinGW gcc compiler. Although this is a nice cross-platform solution, debugging binaries built this way leaves a lot to be desired.&lt;br /&gt;
&lt;br /&gt;
If you own a copy of Visual Studio, you can configure MAME to build using those tools instead. Once you have done that, you can debug problems in MAME using the Visual Studio debugger, which is a huge step up from gdb.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how to make it work:&lt;br /&gt;
&lt;br /&gt;
# You must already have an environment that can build MAME using the MinGW tools. Although you won&#039;t be using gcc to compile, you will be using several of the other tools included in the standard MAME [http://mamedev.org/tools/ MinGW Development Environment]&lt;br /&gt;
# From the command prompt, you need to run the batch file that was installed with Visual Studio which configures the executable, include, and library paths.&lt;br /&gt;
#* For example, on Visual Studio 2005, the command is: &amp;lt;code&amp;gt;&amp;quot;\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat&amp;quot; x86&amp;lt;/code&amp;gt; (To build a 64-bit version, change the &amp;lt;code&amp;gt;x86&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;amd64&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Switch to the directory where the root MAME makefile lives.&lt;br /&gt;
# Once you&#039;ve done that, simply run: &amp;lt;code&amp;gt;make MSVC_BUILD=1 DEBUG=1 SYMBOLS=1&amp;lt;/code&amp;gt; and wait for it to complete (I suggest building with DEBUG=1 as that also disables optimizations and makes debugging much easier).&lt;br /&gt;
&lt;br /&gt;
At this point, you should now have a mamed.exe that was built using Visual Studio tools. To debug it is very easy.&lt;br /&gt;
&lt;br /&gt;
# Open up Visual Studio.&lt;br /&gt;
# From the File menu choose &amp;quot;Open Project...&amp;quot;&lt;br /&gt;
# Select vmamed.exe (you may need to adjust the file filters to show .exe files).&lt;br /&gt;
# To configure command line parameters, right click on the vmamed.exe item in the Solution Explorer window and choose &amp;quot;Properties&amp;quot;. In that window you can specify the &amp;quot;Command Arguments&amp;quot; which would be the command line parameters you want.&lt;br /&gt;
# Set some breakpoints if you want, and hit &amp;quot;Go&amp;quot; (F5), or else single step into main by hitting &amp;quot;Step Into&amp;quot; (F11).&lt;br /&gt;
# When you&#039;re done, Visual Studio will ask if you want to save a solution file (.sln); I usually say &amp;quot;yes&amp;quot;, because then it will remember your last session parameters for the next time you want to debug MAME, and the solution will show up in the recent projects list.&lt;br /&gt;
&lt;br /&gt;
Back to [[How MAME Works]]&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Building_MAME_using_Microsoft_Visual_Studio_compilers&amp;diff=4002</id>
		<title>Building MAME using Microsoft Visual Studio compilers</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Building_MAME_using_Microsoft_Visual_Studio_compilers&amp;diff=4002"/>
		<updated>2012-09-12T18:22:57Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;By default, MAME is configured via the makefile to build using the MinGW gcc compiler. Although this is a nice cross-platform solution, debugging binaries built this way leaves a lot to be desired.&lt;br /&gt;
&lt;br /&gt;
If you own a copy of Visual Studio, you can configure MAME to build using those tools instead. Once you have done that, you can debug problems in MAME using the Visual Studio debugger, which is a huge step up from gdb.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how to make it work:&lt;br /&gt;
&lt;br /&gt;
# You must already have an environment that can build MAME using the MinGW tools. Although you won&#039;t be using gcc to compile, you will be using several of the other tools included in the standard MAME [http://mamedev.org/tools/ MinGW Development Environment]&lt;br /&gt;
# From the command prompt, you need to run the batch file that was installed with Visual Studio which configures the executable, include, and library paths.&lt;br /&gt;
#* For example, on Visual Studio 2005, the command is: &amp;lt;code&amp;gt;&amp;quot;\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat&amp;quot; x86&amp;lt;/code&amp;gt;&lt;br /&gt;
#** (To build a 64-bit version, change the &amp;lt;code&amp;gt;x86&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;amd64&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Switch to the directory where the root MAME makefile lives.&lt;br /&gt;
# Once you&#039;ve done that, simply run: &amp;lt;code&amp;gt;make MSVC_BUILD=1 DEBUG=1 SYMBOLS=1&amp;lt;/code&amp;gt; and wait for it to complete (I suggest building with DEBUG=1 as that also disables optimizations and makes debugging much easier).&lt;br /&gt;
&lt;br /&gt;
At this point, you should now have a mamed.exe that was built using Visual Studio tools. To debug it is very easy.&lt;br /&gt;
&lt;br /&gt;
# Open up Visual Studio.&lt;br /&gt;
# From the File menu choose &amp;quot;Open Project...&amp;quot;&lt;br /&gt;
# Select vmamed.exe (you may need to adjust the file filters to show .exe files).&lt;br /&gt;
# To configure command line parameters, right click on the vmamed.exe item in the Solution Explorer window and choose &amp;quot;Properties&amp;quot;. In that window you can specify the &amp;quot;Command Arguments&amp;quot; which would be the command line parameters you want.&lt;br /&gt;
# Set some breakpoints if you want, and hit &amp;quot;Go&amp;quot; (F5), or else single step into main by hitting &amp;quot;Step Into&amp;quot; (F11).&lt;br /&gt;
# When you&#039;re done, Visual Studio will ask if you want to save a solution file (.sln); I usually say &amp;quot;yes&amp;quot;, because then it will remember your last session parameters for the next time you want to debug MAME, and the solution will show up in the recent projects list.&lt;br /&gt;
&lt;br /&gt;
Back to [[How MAME Works]]&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Submitting_Source_Code&amp;diff=3925</id>
		<title>Submitting Source Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Submitting_Source_Code&amp;diff=3925"/>
		<updated>2012-05-07T15:01:29Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Submission Guidelines */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you&#039;re handy with C and want to help out, there are several ways you can do so. Source code submissions from outside developers are welcome. In fact, many of the more unexpected improvements to MAME come from folks who are not &amp;quot;official&amp;quot; MAME devs. &lt;br /&gt;
&lt;br /&gt;
== Acceptable Submissions ==&lt;br /&gt;
&lt;br /&gt;
When working on modifications to MAME, keep the following guidelines in mind: &lt;br /&gt;
&lt;br /&gt;
* We are not interested in adding features to MAME to make games look better or improve playability or cheat the hardware emulation in order to make things run faster. Submissions that serve only to do this will not be considered. &lt;br /&gt;
* Technical accuracy is our #1 goal. ROM patches or hacks to games are generally not appropriate as they do not improve our understanding of the hardware. Submissions which are merely wild guesses about something and which don&#039;t make sense based on what is known about the hardware will tend to be rejected. &lt;br /&gt;
* ROM set naming in MAME is arbitrary. There is no point in submitting changes to ROM set names; they are crammed into 8 characters and have many other limitations. Plus it tends to annoy the developers. &lt;br /&gt;
* If you think there is a problem in the naming of a game, you should [http://mamedev.org/contact.html?team send an email] rather than a source code patch. Game names changes are discussed among the developers and aren&#039;t really code changes. &lt;br /&gt;
* Cosmetic changes to the source are best left up to the core developers. If your change doesn&#039;t add anything worthwhile to the actual code, it is not worth your time to submit it. &lt;br /&gt;
&lt;br /&gt;
== Submission Guidelines ==&lt;br /&gt;
&lt;br /&gt;
Before sending in a submission, you should make sure that you follow these guidelines: &lt;br /&gt;
&lt;br /&gt;
* All submissions must be compiled in both debug (make DEBUG=1) and non-debug builds using the official build tools (download them from here), and all warnings or errors fixed. &lt;br /&gt;
* All submissions should be in diff format, taken against the [http://mamedev.org/release.html most recent intermediate update]. (If you are using Windows, you can get a set of diff/patch tools [http://mamedev.org/tools/diffpatch-mingw.exe here].) &lt;br /&gt;
* To create a correct diff, use the following command line: &lt;br /&gt;
 diff -Nru originaltree modifiedtree &amp;gt;patchname.diff &lt;br /&gt;
where originaltree is the &#039;src&#039; directory of the original, unmodified sources; modifiedtree is the &#039;src&#039; directory of your updated sources; and patchname.diff is the name of the diff you want to create. &lt;br /&gt;
* Once you have a .diff containing your changes, ZIP it up and submit it by sending email to [[image:Submit-email.png|frameless|122x12px|baseline]]. &lt;br /&gt;
&lt;br /&gt;
Submissions are most often accepted or rejected without feedback. If you submitted something and it hasn&#039;t shown up in MAME within a few intermediate releases, feel free to ask what the status of your submission is.&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
&lt;br /&gt;
MAME is a huge project, and to work on many parts of it requires extensive understanding of C, arcade game hardware, CPU architectures, audio systems, graphics systems, and reverse engineering. These are not easy to come by, and the learning curve is very steep. That said, there are still ways of contributing to MAME that don&#039;t require a full top-to-bottom understanding of everything. Here are a couple of suggestions: &lt;br /&gt;
&lt;br /&gt;
# Add save state support to a driver. The save state system is very modular and pretty straightforward to use. Furthermore, very few drivers are set up to use it right now. Digging into a driver and figuring out what data needs to be preserved in order to resume execution is a great way to learn about MAME. &lt;br /&gt;
# Figure out what unknown DIP switches do. Some of this can be determined by twiddling the DIP switches and watching what happens, but often this is not enough. Delving into the game code to understand how the DIP switches are read and what their values are used for is a good beginning challenge in reverse engineering. &lt;br /&gt;
# Go to [http://www.mametesters.org/ MAMETesters] and look over the bugs. There are many tricky bugs in there, but there are also many straightforward issues that nobody has yet taken the time to look into. &lt;br /&gt;
&lt;br /&gt;
If you&#039;re new to emulator programming, these are a far better places to start than trying to tackle the emulation of a game that doesn&#039;t yet work. Any games that still don&#039;t work are usually due to complicated protection or hardware emulation issues and are more than likely going to be a daunting (and discouraging) challenge for someone just getting started.&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=File:Submit-email.png&amp;diff=3924</id>
		<title>File:Submit-email.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=File:Submit-email.png&amp;diff=3924"/>
		<updated>2012-05-07T14:49:07Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3224</id>
		<title>Device Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3224"/>
		<updated>2010-06-10T20:23:19Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Memory */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Device interfaces are separate classes that enable devices to participate in more areas of the overall system. Each interface is a sort of contract between the device that inherits from it and related other parts of the system. For example, a device inherits from the execute interface if it wishes to be scheduled and called regularly to execute. Simiarly, a device inherits from the NVRAM interface if it wishes to participate in saving/loading data to the .nv files.&lt;br /&gt;
&lt;br /&gt;
To add an interface to a device, both the device class and device&#039;s configuration class must inherit from the interface&#039;s class and the interface&#039;s configuration class, respectively. Some interfaces are more about configuration than runtime, and others are more about runtime than configuration, but in all cases both interface classes are required.&lt;br /&gt;
&lt;br /&gt;
Since a device is already required to inherit from device_t, this means that you must leverage C++&#039;s &amp;lt;i&amp;gt;multiple inheritance&amp;lt;/i&amp;gt; support in order to add an interface. For example, our configuration class might look like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config,&lt;br /&gt;
                                public device_config_memory_interface,&lt;br /&gt;
                                public device_config_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and our device class like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device : public device_t,&lt;br /&gt;
                         public device_memory_interface,&lt;br /&gt;
                         public device_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Notice first that the &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;device_t&#039;&#039;&#039; classes remain the first classes listed. This is important as they are the real base classes of our device. The interface classes should always be listed afterwards. Also notice that our configuration class and our device class inherit from matching configuration and interface classes.&lt;br /&gt;
&lt;br /&gt;
Each interface has its own demands on the device. Some interfaces, like the sound interface, really don&#039;t require any significant changes. Others, like the NVRAM interface, are pure virtual classes, requiring implementation of one or more methods.&lt;br /&gt;
&lt;br /&gt;
Currently the MAME core defines six standard interfaces:&lt;br /&gt;
&lt;br /&gt;
* The execute interface connects the device to the internal scheduler, and requires implementation of a &#039;&#039;&#039;device_run&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* The memory interface connects the device to the memory system, allowing it to specify one or more address spaces.&lt;br /&gt;
&lt;br /&gt;
* The state interface connects the device to the debugger, enabling display and editing of state during execution from within the register view. It also provides simple indexed accessors for reading/writing state in a standard fashion.&lt;br /&gt;
&lt;br /&gt;
* The NVRAM interface connects the device to the NVRAM read/write process.&lt;br /&gt;
&lt;br /&gt;
* The disassembly interface connects the device to the debugger, enabling disassembly views from within the disassembly window.&lt;br /&gt;
&lt;br /&gt;
* The sound interface connects the device to the sound network, enabling routing of sound from the device to/from other devices.&lt;br /&gt;
&lt;br /&gt;
Details on the interfaces and their requirements are given in the sections below.&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
This section has descriptions of each of the standard device interfaces.&lt;br /&gt;
&lt;br /&gt;
==Execute==&lt;br /&gt;
&lt;br /&gt;
The execute interface enables a device to participate in the standard device scheduling. The scheduler makes a list of all devices with execute interfaces, and then iterates through them, assigning each a timeslice and requesting the device to execute. &lt;br /&gt;
&lt;br /&gt;
The execute interface also provides mechanisms for interrupt signalling and synchronization, allowing the device to participate properly in the execution of the aggregate system. &lt;br /&gt;
&lt;br /&gt;
Finally, the configuration portion of the execute interface automatically supports the MDRV_DEVICE_DISABLE() configuration tokens, which allow an executable device to exist in a configuration but prevents it from event being scheduled.&lt;br /&gt;
&lt;br /&gt;
A device configuration class that inherits from &#039;&#039;&#039;device_config_execute_interface&#039;&#039;&#039; can optionally override several methods that describe how the device executes:&lt;br /&gt;
&lt;br /&gt;
 class example2_device_config : public device_config,&lt;br /&gt;
                                public device_config_execute_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_config_execute_interface overrides&lt;br /&gt;
     virtual UINT32 execute_clocks_to_cycles(UINT32 clocks) const;&lt;br /&gt;
     virtual UINT32 execute_cycles_to_clocks(UINT32 cycles) const;&lt;br /&gt;
     virtual UINT32 execute_min_cycles() const;&lt;br /&gt;
     virtual UINT32 execute_max_cycles() const;&lt;br /&gt;
     virtual UINT32 execute_input_lines() const;&lt;br /&gt;
     virtual UINT32 execute_default_irq_vector() const;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The first two overrides provide methods that translate from clocks to cycles and vice-versa. A &#039;&#039;&#039;clock&#039;&#039;&#039; is defined as a single cycle of the input clock to the device. A &#039;&#039;&#039;cycle&#039;&#039;&#039; is defined as an internal unit used by the device when executing. By default, it is assumed that 1 clock == 1 cycle. However, if your device has an internal clock divider or multiplier, these methods should be overridden to do the math and return the proper numbers.&lt;br /&gt;
&lt;br /&gt;
The middle two overrides should simply return the minimum and maximum number of cycles that any given execution step in your device may take. For example, if you are describing a CPU whose fastest instruction takes 2 cycles and whose slowest instruction takes 10 cycles, you would override these two methods to return the values 2 and 10, respectively. Note that these numbers are in cycles, not clocks. If not provided, these values both default to 1 cycle.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;execute_input_lines&#039;&#039;&#039;() override should simply return the number of synchronized input lines attached to the device. By default, this is 0.&lt;br /&gt;
&lt;br /&gt;
Finally, the &#039;&#039;&#039;execute_default_irq_vector&#039;&#039;&#039;() override should return the default integer vector that is implicitly specified when signalling an input line without explicitly providing a vector.&lt;br /&gt;
&lt;br /&gt;
Moving on to the device class:&lt;br /&gt;
&lt;br /&gt;
 class example2_device : public device_t,&lt;br /&gt;
                         public device_execute_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_execute_interface overrides&lt;br /&gt;
     virtual INT32 execute_run(INT32 cycles);&lt;br /&gt;
     virtual void execute_burn(INT32 cycles);&lt;br /&gt;
     virtual void execute_set_input(int linenum, int state);&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The most important (and only required) override here is &#039;&#039;&#039;execute_run&#039;&#039;&#039;() which is called whenever the device is scheduled for execution. It is passed the number of cycles (not clocks) to execute, and when it is finished, it should return the number of cycles that were executed.&lt;br /&gt;
&lt;br /&gt;
The optional override &#039;&#039;&#039;execute_burn&#039;&#039;&#039;() is called if the device execution is suspended for any reason, but cycles are consumed. This is generally used to support internal running clocks or other things which need to keep track of how many cycles executed.&lt;br /&gt;
&lt;br /&gt;
Finally, the &#039;&#039;&#039;execute_set_input&#039;&#039;&#039;() override is called whenever a synchronized input is changed. Internally, the execute interface accepts synchronized input change requests, queues them, and then calls this override at the appropriate time to ensure the state is updated in sync with all other executing devices.&lt;br /&gt;
&lt;br /&gt;
==Memory==&lt;br /&gt;
&lt;br /&gt;
The memory interface allows to a device to own one or more address spaces. These address spaces are detected by the memory system and automatically allocated at startup time. Memory interfaces are most commonly used for CPU cores, though any device that accesses memory out over a bus should ideally use an address space for those accesses so that bank switching or other mechanisms can be implemented to act upon reads/writes to that address space.&lt;br /&gt;
&lt;br /&gt;
The configuration portion of the memory interface automatically supports the MDRV_DEVICE_ADDRESS_MAP() configuration tokens. These allow an address map to be expressed in a driver, which the memory system turns into an address space at startup.&lt;br /&gt;
&lt;br /&gt;
A device configuration class that inherits from &#039;&#039;&#039;device_config_memory_interface&#039;&#039;&#039; is required to override a method that returns an &#039;&#039;&#039;adress_space_config&#039;&#039;&#039; pointer for a given address space index:&lt;br /&gt;
&lt;br /&gt;
 class example3_device_config : public device_config,&lt;br /&gt;
                                public device_config_memory_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_config_memory_interface overrides&lt;br /&gt;
     const address_space_config *space_config(int spacenum = 0) const;&lt;br /&gt;
 &lt;br /&gt;
     // address space configurations&lt;br /&gt;
     address_space_config   m_program_space;&lt;br /&gt;
     address_space_config   m_io_space;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;space_config&#039;&#039;&#039; override accepts a space index and returns a pointer to an &#039;&#039;&#039;adress_space_config&#039;&#039;&#039; object. In general, the configuration of the address space is fixed for a device, so it is typical to just embed these objects and initialize them in the constructor. For example:&lt;br /&gt;
&lt;br /&gt;
 example3_device_config::example3_device_config(const machine_config &amp;amp;mconfig, const char *tag, &lt;br /&gt;
         const device_config *owner, UINT32 clock)&lt;br /&gt;
     : device_config(mconfig, static_alloc_device_config, tag, owner, clock),&lt;br /&gt;
       device_config_memory_interface(mconfig, *this),&lt;br /&gt;
       m_program_space(&amp;quot;program&amp;quot;, ENDIANNESS_LITTLE, 32, 32, 0, 32, 12),&lt;br /&gt;
       m_io_space(&amp;quot;data&amp;quot;, ENDIANNESS_LITTLE, 32, 16)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a &amp;quot;program&amp;quot; memory space that is 32-bit little-endian with a 32-bit address bus, a 32-bit logical address space, and 12-bit pages; and a &amp;quot;data&amp;quot; memory space that is also 32-bit little-endian with a 16-bit address bus.&lt;br /&gt;
&lt;br /&gt;
Given this, then the &#039;&#039;&#039;space_config&#039;&#039;&#039; looks like:&lt;br /&gt;
&lt;br /&gt;
 const address_space_config *space_config(int spacenum) const&lt;br /&gt;
 {&lt;br /&gt;
     if (spacenum == AS_PROGRAM)&lt;br /&gt;
         return &amp;amp;m_program_space;&lt;br /&gt;
     else if (spacenum == AS_IO)&lt;br /&gt;
         return &amp;amp;m_io_space;&lt;br /&gt;
     else&lt;br /&gt;
         return NULL;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Moving on to the device class:&lt;br /&gt;
&lt;br /&gt;
 class example2_device : public device_t,&lt;br /&gt;
                         public device_memory_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_execute_interface overrides&lt;br /&gt;
     virtual bool memory_translate(int spacenum, int intention, offs_t &amp;amp;address);&lt;br /&gt;
     virtual bool memory_read(int spacenum, offs_t offset, int size, UINT64 &amp;amp;value);&lt;br /&gt;
     virtual bool memory_write(int spacenum, offs_t offset, int size, UINT64 value);&lt;br /&gt;
     virtual bool memory_readop(offs_t offset, int size, UINT64 &amp;amp;value);&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
All of these methods are optional. For devices that support virtual address spaces (e.g., address translation), you will want to override the &#039;&#039;&#039;memory_translate&#039;&#039;&#039;() method which allows you to transform logical addresses to physical addresses, or return false if there is no mapping for the provided address.&lt;br /&gt;
&lt;br /&gt;
The remaining three overrides are primarily for debugging, and allow the device a chance to act on reads, writes, and opcode reads before they are passed to the memory system. Return true if your method handled the operation to prevent it from being passed on.&lt;br /&gt;
&lt;br /&gt;
==State==&lt;br /&gt;
&lt;br /&gt;
==NVRAM==&lt;br /&gt;
&lt;br /&gt;
==Disassembly==&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3223</id>
		<title>Device Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3223"/>
		<updated>2010-06-10T20:22:44Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Standard Interfaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Device interfaces are separate classes that enable devices to participate in more areas of the overall system. Each interface is a sort of contract between the device that inherits from it and related other parts of the system. For example, a device inherits from the execute interface if it wishes to be scheduled and called regularly to execute. Simiarly, a device inherits from the NVRAM interface if it wishes to participate in saving/loading data to the .nv files.&lt;br /&gt;
&lt;br /&gt;
To add an interface to a device, both the device class and device&#039;s configuration class must inherit from the interface&#039;s class and the interface&#039;s configuration class, respectively. Some interfaces are more about configuration than runtime, and others are more about runtime than configuration, but in all cases both interface classes are required.&lt;br /&gt;
&lt;br /&gt;
Since a device is already required to inherit from device_t, this means that you must leverage C++&#039;s &amp;lt;i&amp;gt;multiple inheritance&amp;lt;/i&amp;gt; support in order to add an interface. For example, our configuration class might look like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config,&lt;br /&gt;
                                public device_config_memory_interface,&lt;br /&gt;
                                public device_config_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and our device class like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device : public device_t,&lt;br /&gt;
                         public device_memory_interface,&lt;br /&gt;
                         public device_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Notice first that the &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;device_t&#039;&#039;&#039; classes remain the first classes listed. This is important as they are the real base classes of our device. The interface classes should always be listed afterwards. Also notice that our configuration class and our device class inherit from matching configuration and interface classes.&lt;br /&gt;
&lt;br /&gt;
Each interface has its own demands on the device. Some interfaces, like the sound interface, really don&#039;t require any significant changes. Others, like the NVRAM interface, are pure virtual classes, requiring implementation of one or more methods.&lt;br /&gt;
&lt;br /&gt;
Currently the MAME core defines six standard interfaces:&lt;br /&gt;
&lt;br /&gt;
* The execute interface connects the device to the internal scheduler, and requires implementation of a &#039;&#039;&#039;device_run&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* The memory interface connects the device to the memory system, allowing it to specify one or more address spaces.&lt;br /&gt;
&lt;br /&gt;
* The state interface connects the device to the debugger, enabling display and editing of state during execution from within the register view. It also provides simple indexed accessors for reading/writing state in a standard fashion.&lt;br /&gt;
&lt;br /&gt;
* The NVRAM interface connects the device to the NVRAM read/write process.&lt;br /&gt;
&lt;br /&gt;
* The disassembly interface connects the device to the debugger, enabling disassembly views from within the disassembly window.&lt;br /&gt;
&lt;br /&gt;
* The sound interface connects the device to the sound network, enabling routing of sound from the device to/from other devices.&lt;br /&gt;
&lt;br /&gt;
Details on the interfaces and their requirements are given in the sections below.&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
This section has descriptions of each of the standard device interfaces.&lt;br /&gt;
&lt;br /&gt;
==Execute==&lt;br /&gt;
&lt;br /&gt;
The execute interface enables a device to participate in the standard device scheduling. The scheduler makes a list of all devices with execute interfaces, and then iterates through them, assigning each a timeslice and requesting the device to execute. &lt;br /&gt;
&lt;br /&gt;
The execute interface also provides mechanisms for interrupt signalling and synchronization, allowing the device to participate properly in the execution of the aggregate system. &lt;br /&gt;
&lt;br /&gt;
Finally, the configuration portion of the execute interface automatically supports the MDRV_DEVICE_DISABLE() configuration tokens, which allow an executable device to exist in a configuration but prevents it from event being scheduled.&lt;br /&gt;
&lt;br /&gt;
A device configuration class that inherits from &#039;&#039;&#039;device_config_execute_interface&#039;&#039;&#039; can optionally override several methods that describe how the device executes:&lt;br /&gt;
&lt;br /&gt;
 class example2_device_config : public device_config,&lt;br /&gt;
                                public device_config_execute_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_config_execute_interface overrides&lt;br /&gt;
     virtual UINT32 execute_clocks_to_cycles(UINT32 clocks) const;&lt;br /&gt;
     virtual UINT32 execute_cycles_to_clocks(UINT32 cycles) const;&lt;br /&gt;
     virtual UINT32 execute_min_cycles() const;&lt;br /&gt;
     virtual UINT32 execute_max_cycles() const;&lt;br /&gt;
     virtual UINT32 execute_input_lines() const;&lt;br /&gt;
     virtual UINT32 execute_default_irq_vector() const;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The first two overrides provide methods that translate from clocks to cycles and vice-versa. A &#039;&#039;&#039;clock&#039;&#039;&#039; is defined as a single cycle of the input clock to the device. A &#039;&#039;&#039;cycle&#039;&#039;&#039; is defined as an internal unit used by the device when executing. By default, it is assumed that 1 clock == 1 cycle. However, if your device has an internal clock divider or multiplier, these methods should be overridden to do the math and return the proper numbers.&lt;br /&gt;
&lt;br /&gt;
The middle two overrides should simply return the minimum and maximum number of cycles that any given execution step in your device may take. For example, if you are describing a CPU whose fastest instruction takes 2 cycles and whose slowest instruction takes 10 cycles, you would override these two methods to return the values 2 and 10, respectively. Note that these numbers are in cycles, not clocks. If not provided, these values both default to 1 cycle.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;execute_input_lines&#039;&#039;&#039;() override should simply return the number of synchronized input lines attached to the device. By default, this is 0.&lt;br /&gt;
&lt;br /&gt;
Finally, the &#039;&#039;&#039;execute_default_irq_vector&#039;&#039;&#039;() override should return the default integer vector that is implicitly specified when signalling an input line without explicitly providing a vector.&lt;br /&gt;
&lt;br /&gt;
Moving on to the device class:&lt;br /&gt;
&lt;br /&gt;
 class example2_device : public device_t,&lt;br /&gt;
                         public device_execute_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_execute_interface overrides&lt;br /&gt;
     virtual INT32 execute_run(INT32 cycles);&lt;br /&gt;
     virtual void execute_burn(INT32 cycles);&lt;br /&gt;
     virtual void execute_set_input(int linenum, int state);&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The most important (and only required) override here is &#039;&#039;&#039;execute_run&#039;&#039;&#039;() which is called whenever the device is scheduled for execution. It is passed the number of cycles (not clocks) to execute, and when it is finished, it should return the number of cycles that were executed.&lt;br /&gt;
&lt;br /&gt;
The optional override &#039;&#039;&#039;execute_burn&#039;&#039;&#039;() is called if the device execution is suspended for any reason, but cycles are consumed. This is generally used to support internal running clocks or other things which need to keep track of how many cycles executed.&lt;br /&gt;
&lt;br /&gt;
Finally, the &#039;&#039;&#039;execute_set_input&#039;&#039;&#039;() override is called whenever a synchronized input is changed. Internally, the execute interface accepts synchronized input change requests, queues them, and then calls this override at the appropriate time to ensure the state is updated in sync with all other executing devices.&lt;br /&gt;
&lt;br /&gt;
==Memory==&lt;br /&gt;
&lt;br /&gt;
The memory interface allows to a device to own one or more address spaces. These address spaces are detected by the memory system and automatically allocated at startup time. Memory interfaces are most commonly used for CPU cores, though any device that accesses memory out over a bus should ideally use an address space for those accesses so that bank switching or other mechanisms can be implemented to act upon reads/writes to that address space.&lt;br /&gt;
&lt;br /&gt;
The configuration portion of the memory interface automatically supports the MDRV_DEVICE_ADDRESS_MAP() configuration tokens. These allow an address map to be expressed in a driver, which the memory system turns into an address space at startup.&lt;br /&gt;
&lt;br /&gt;
A device configuration class that inherits from &#039;&#039;&#039;device_config_memory_interface&#039;&#039;&#039; is required to override a method that returns an &#039;&#039;&#039;adress_space_config&#039;&#039;&#039; pointer for a given address space index:&lt;br /&gt;
&lt;br /&gt;
 class example3_device_config : public device_config,&lt;br /&gt;
                                public device_config_memory_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_config_memory_interface overrides&lt;br /&gt;
     const address_space_config *space_config(int spacenum = 0) const;&lt;br /&gt;
&lt;br /&gt;
     // address space configurations&lt;br /&gt;
     address_space_config   m_program_space;&lt;br /&gt;
     address_space_config   m_io_space;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;space_config&#039;&#039;&#039; override accepts a space index and returns a pointer to an &#039;&#039;&#039;adress_space_config&#039;&#039;&#039; object. In general, the configuration of the address space is fixed for a device, so it is typical to just embed these objects and initialize them in the constructor. For example:&lt;br /&gt;
&lt;br /&gt;
 example3_device_config::example3_device_config(const machine_config &amp;amp;mconfig, const char *tag, &lt;br /&gt;
         const device_config *owner, UINT32 clock)&lt;br /&gt;
     : device_config(mconfig, static_alloc_device_config, tag, owner, clock),&lt;br /&gt;
       device_config_memory_interface(mconfig, *this),&lt;br /&gt;
       m_program_space(&amp;quot;program&amp;quot;, ENDIANNESS_LITTLE, 32, 32, 0, 32, 12),&lt;br /&gt;
       m_io_space(&amp;quot;data&amp;quot;, ENDIANNESS_LITTLE, 32, 16)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a &amp;quot;program&amp;quot; memory space that is 32-bit little-endian with a 32-bit address bus, a 32-bit logical address space, and 12-bit pages; and a &amp;quot;data&amp;quot; memory space that is also 32-bit little-endian with a 16-bit address bus.&lt;br /&gt;
&lt;br /&gt;
Given this, then the &#039;&#039;&#039;space_config&#039;&#039;&#039; looks like:&lt;br /&gt;
&lt;br /&gt;
 const address_space_config *space_config(int spacenum) const&lt;br /&gt;
 {&lt;br /&gt;
     if (spacenum == AS_PROGRAM)&lt;br /&gt;
         return &amp;amp;m_program_space;&lt;br /&gt;
     else if (spacenum == AS_IO)&lt;br /&gt;
         return &amp;amp;m_io_space;&lt;br /&gt;
     else&lt;br /&gt;
         return NULL;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Moving on to the device class:&lt;br /&gt;
&lt;br /&gt;
 class example2_device : public device_t,&lt;br /&gt;
                         public device_memory_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_execute_interface overrides&lt;br /&gt;
     virtual bool memory_translate(int spacenum, int intention, offs_t &amp;amp;address);&lt;br /&gt;
     virtual bool memory_read(int spacenum, offs_t offset, int size, UINT64 &amp;amp;value);&lt;br /&gt;
     virtual bool memory_write(int spacenum, offs_t offset, int size, UINT64 value);&lt;br /&gt;
     virtual bool memory_readop(offs_t offset, int size, UINT64 &amp;amp;value);&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
All of these methods are optional. For devices that support virtual address spaces (e.g., address translation), you will want to override the &#039;&#039;&#039;memory_translate&#039;&#039;&#039;() method which allows you to transform logical addresses to physical addresses, or return false if there is no mapping for the provided address.&lt;br /&gt;
&lt;br /&gt;
The remaining three overrides are primarily for debugging, and allow the device a chance to act on reads, writes, and opcode reads before they are passed to the memory system. Return true if your method handled the operation to prevent it from being passed on.&lt;br /&gt;
&lt;br /&gt;
==State==&lt;br /&gt;
&lt;br /&gt;
==NVRAM==&lt;br /&gt;
&lt;br /&gt;
==Disassembly==&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3222</id>
		<title>Device Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3222"/>
		<updated>2010-06-08T19:49:25Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Execute */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Device interfaces are separate classes that enable devices to participate in more areas of the overall system. Each interface is a sort of contract between the device that inherits from it and related other parts of the system. For example, a device inherits from the execute interface if it wishes to be scheduled and called regularly to execute. Simiarly, a device inherits from the NVRAM interface if it wishes to participate in saving/loading data to the .nv files.&lt;br /&gt;
&lt;br /&gt;
To add an interface to a device, both the device class and device&#039;s configuration class must inherit from the interface&#039;s class and the interface&#039;s configuration class, respectively. Some interfaces are more about configuration than runtime, and others are more about runtime than configuration, but in all cases both interface classes are required.&lt;br /&gt;
&lt;br /&gt;
Since a device is already required to inherit from device_t, this means that you must leverage C++&#039;s &amp;lt;i&amp;gt;multiple inheritance&amp;lt;/i&amp;gt; support in order to add an interface. For example, our configuration class might look like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config,&lt;br /&gt;
                                public device_config_memory_interface,&lt;br /&gt;
                                public device_config_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and our device class like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device : public device_t,&lt;br /&gt;
                         public device_memory_interface,&lt;br /&gt;
                         public device_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Notice first that the &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;device_t&#039;&#039;&#039; classes remain the first classes listed. This is important as they are the real base classes of our device. The interface classes should always be listed afterwards. Also notice that our configuration class and our device class inherit from matching configuration and interface classes.&lt;br /&gt;
&lt;br /&gt;
Each interface has its own demands on the device. Some interfaces, like the sound interface, really don&#039;t require any significant changes. Others, like the NVRAM interface, are pure virtual classes, requiring implementation of one or more methods.&lt;br /&gt;
&lt;br /&gt;
Currently the MAME core defines six standard interfaces:&lt;br /&gt;
&lt;br /&gt;
* The execute interface connects the device to the internal scheduler, and requires implementation of a &#039;&#039;&#039;device_run&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* The memory interface connects the device to the memory system, allowing it to specify one or more address spaces.&lt;br /&gt;
&lt;br /&gt;
* The state interface connects the device to the debugger, enabling display and editing of state during execution from within the register view. It also provides simple indexed accessors for reading/writing state in a standard fashion.&lt;br /&gt;
&lt;br /&gt;
* The NVRAM interface connects the device to the NVRAM read/write process.&lt;br /&gt;
&lt;br /&gt;
* The disassembly interface connects the device to the debugger, enabling disassembly views from within the disassembly window.&lt;br /&gt;
&lt;br /&gt;
* The sound interface connects the device to the sound network, enabling routing of sound from the device to/from other devices.&lt;br /&gt;
&lt;br /&gt;
Details on the interfaces and their requirements are given in the sections below.&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
This section has descriptions of each of the standard device interfaces.&lt;br /&gt;
&lt;br /&gt;
==Execute==&lt;br /&gt;
&lt;br /&gt;
The execute interface enables a device to participate in the standard device scheduling. The scheduler makes a list of all devices with execute interfaces, and then iterates through them, assigning each a timeslice and requesting the device to execute. The execute interface also provides mechanisms for interrupt signalling and synchronization, allowing the device to participate properly in the execution of the aggregate system.&lt;br /&gt;
&lt;br /&gt;
A device configuration class that inherits from &#039;&#039;&#039;device_config_execute_interface&#039;&#039;&#039; can optionally override several methods that describe how the device executes:&lt;br /&gt;
&lt;br /&gt;
 class example2_device_config : public device_config,&lt;br /&gt;
                                public device_config_execute_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_config_execute_interface overrides&lt;br /&gt;
     virtual UINT32 execute_clocks_to_cycles(UINT32 clocks) const;&lt;br /&gt;
     virtual UINT32 execute_cycles_to_clocks(UINT32 cycles) const;&lt;br /&gt;
     virtual UINT32 execute_min_cycles() const;&lt;br /&gt;
     virtual UINT32 execute_max_cycles() const;&lt;br /&gt;
     virtual UINT32 execute_input_lines() const;&lt;br /&gt;
     virtual UINT32 execute_default_irq_vector() const;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The first two overrides provide methods that translate from clocks to cycles and vice-versa. A &#039;&#039;&#039;clock&#039;&#039;&#039; is defined as a single cycle of the input clock to the device. A &#039;&#039;&#039;cycle&#039;&#039;&#039; is defined as an internal unit used by the device when executing. By default, it is assumed that 1 clock == 1 cycle. However, if your device has an internal clock divider or multiplier, these methods should be overridden to do the math and return the proper numbers.&lt;br /&gt;
&lt;br /&gt;
The middle two overrides should simply return the minimum and maximum number of cycles that any given execution step in your device may take. For example, if you are describing a CPU whose fastest instruction takes 2 cycles and whose slowest instruction takes 10 cycles, you would override these two methods to return the values 2 and 10, respectively. Note that these numbers are in cycles, not clocks. If not provided, these values both default to 1 cycle.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;execute_input_lines&#039;&#039;&#039;() override should simply return the number of synchronized input lines attached to the device. By default, this is 0.&lt;br /&gt;
&lt;br /&gt;
Finally, the &#039;&#039;&#039;execute_default_irq_vector&#039;&#039;&#039;() override should return the default integer vector that is implicitly specified when signalling an input line without explicitly providing a vector.&lt;br /&gt;
&lt;br /&gt;
Moving on to the device class:&lt;br /&gt;
&lt;br /&gt;
 class example2_device : public device_t,&lt;br /&gt;
                         public device_execute_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device_execute_interface overrides&lt;br /&gt;
     virtual INT32 execute_run(INT32 cycles);&lt;br /&gt;
     virtual void execute_burn(INT32 cycles);&lt;br /&gt;
     virtual void execute_set_input(int linenum, int state);&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The most important (and only required) override here is &#039;&#039;&#039;execute_run&#039;&#039;&#039;() which is called whenever the device is scheduled for execution. It is passed the number of cycles (not clocks) to execute, and when it is finished, it should return the number of cycles that were executed.&lt;br /&gt;
&lt;br /&gt;
The optional override &#039;&#039;&#039;execute_burn&#039;&#039;&#039;() is called if the device execution is suspended for any reason, but cycles are consumed. This is generally used to support internal running clocks or other things which need to keep track of how many cycles executed.&lt;br /&gt;
&lt;br /&gt;
Finally, the &#039;&#039;&#039;execute_set_input&#039;&#039;&#039;() override is called whenever a synchronized input is changed. Internally, the execute interface accepts synchronized input change requests, queues them, and then calls this override at the appropriate time to ensure the state is updated in sync with all other executing devices.&lt;br /&gt;
&lt;br /&gt;
==Memory==&lt;br /&gt;
&lt;br /&gt;
==State==&lt;br /&gt;
&lt;br /&gt;
==NVRAM==&lt;br /&gt;
&lt;br /&gt;
==Disassembly==&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3221</id>
		<title>Device Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3221"/>
		<updated>2010-06-08T19:43:36Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Standard Interfaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Device interfaces are separate classes that enable devices to participate in more areas of the overall system. Each interface is a sort of contract between the device that inherits from it and related other parts of the system. For example, a device inherits from the execute interface if it wishes to be scheduled and called regularly to execute. Simiarly, a device inherits from the NVRAM interface if it wishes to participate in saving/loading data to the .nv files.&lt;br /&gt;
&lt;br /&gt;
To add an interface to a device, both the device class and device&#039;s configuration class must inherit from the interface&#039;s class and the interface&#039;s configuration class, respectively. Some interfaces are more about configuration than runtime, and others are more about runtime than configuration, but in all cases both interface classes are required.&lt;br /&gt;
&lt;br /&gt;
Since a device is already required to inherit from device_t, this means that you must leverage C++&#039;s &amp;lt;i&amp;gt;multiple inheritance&amp;lt;/i&amp;gt; support in order to add an interface. For example, our configuration class might look like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config,&lt;br /&gt;
                                public device_config_memory_interface,&lt;br /&gt;
                                public device_config_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and our device class like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device : public device_t,&lt;br /&gt;
                         public device_memory_interface,&lt;br /&gt;
                         public device_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Notice first that the &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;device_t&#039;&#039;&#039; classes remain the first classes listed. This is important as they are the real base classes of our device. The interface classes should always be listed afterwards. Also notice that our configuration class and our device class inherit from matching configuration and interface classes.&lt;br /&gt;
&lt;br /&gt;
Each interface has its own demands on the device. Some interfaces, like the sound interface, really don&#039;t require any significant changes. Others, like the NVRAM interface, are pure virtual classes, requiring implementation of one or more methods.&lt;br /&gt;
&lt;br /&gt;
Currently the MAME core defines six standard interfaces:&lt;br /&gt;
&lt;br /&gt;
* The execute interface connects the device to the internal scheduler, and requires implementation of a &#039;&#039;&#039;device_run&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* The memory interface connects the device to the memory system, allowing it to specify one or more address spaces.&lt;br /&gt;
&lt;br /&gt;
* The state interface connects the device to the debugger, enabling display and editing of state during execution from within the register view. It also provides simple indexed accessors for reading/writing state in a standard fashion.&lt;br /&gt;
&lt;br /&gt;
* The NVRAM interface connects the device to the NVRAM read/write process.&lt;br /&gt;
&lt;br /&gt;
* The disassembly interface connects the device to the debugger, enabling disassembly views from within the disassembly window.&lt;br /&gt;
&lt;br /&gt;
* The sound interface connects the device to the sound network, enabling routing of sound from the device to/from other devices.&lt;br /&gt;
&lt;br /&gt;
Details on the interfaces and their requirements are given in the sections below.&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
This section has descriptions of each of the standard device interfaces.&lt;br /&gt;
&lt;br /&gt;
==Execute==&lt;br /&gt;
&lt;br /&gt;
The execute interface enables a device to participate in the standard device scheduling. The scheduler makes a list of all devices with execute interfaces, and then iterates through them, assigning each a timeslice and requesting the device to execute. The execute interface also provides mechanisms for interrupt signalling and synchronization, allowing the device to participate properly in the execution of the aggregate system.&lt;br /&gt;
&lt;br /&gt;
A device configuration class that inherits from &#039;&#039;&#039;device_config_execute_interface&#039;&#039;&#039; can optionally override several methods that describe how the device executes:&lt;br /&gt;
&lt;br /&gt;
 class example2_device_config : public device_config,&lt;br /&gt;
                                public device_config_execute_interface&lt;br /&gt;
 {&lt;br /&gt;
     // normal device stuff here&lt;br /&gt;
&lt;br /&gt;
 protected:&lt;br /&gt;
     // device_config_execute_interface overrides&lt;br /&gt;
     virtual UINT32 execute_clocks_to_cycles(UINT32 clocks) const;&lt;br /&gt;
     virtual UINT32 execute_cycles_to_clocks(UINT32 cycles) const;&lt;br /&gt;
     virtual UINT32 execute_min_cycles() const;&lt;br /&gt;
     virtual UINT32 execute_max_cycles() const;&lt;br /&gt;
     virtual UINT32 execute_input_lines() const;&lt;br /&gt;
     virtual UINT32 execute_default_irq_vector() const;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The first two overrides provide methods that translate from clocks to cycles and vice-versa. A &#039;&#039;&#039;clock&#039;&#039;&#039; is defined as a single cycle of the input clock to the device. A &#039;&#039;&#039;cycle&#039;&#039;&#039; is defined as an internal unit used by the device when executing. By default, it is assumed that 1 clock == 1 cycle. However, if your device has an internal clock divider or multiplier, these methods should be overridden to do the math and return the proper numbers.&lt;br /&gt;
&lt;br /&gt;
The middle two overrides should simply return the minimum and maximum number of cycles that any given execution step in your device may take. For example, if you are describing a CPU whose fastest instruction takes 2 cycles and whose slowest instruction takes 10 cycles, you would override these two methods to return the values 2 and 10, respectively. Note that these numbers are in cycles, not clocks. If not provided, these values both default to 1 cycle.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;execute_input_lines&#039;&#039;&#039;() override should simply return the number of synchronized input lines attached to the device. By default, this is 0.&lt;br /&gt;
&lt;br /&gt;
Finally, the &#039;&#039;&#039;execute_default_irq_vector&#039;&#039;&#039;() override should return the default integer vector that is implicitly specified when signalling an input line without explicitly providing a vector.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Memory==&lt;br /&gt;
&lt;br /&gt;
==State==&lt;br /&gt;
&lt;br /&gt;
==NVRAM==&lt;br /&gt;
&lt;br /&gt;
==Disassembly==&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3220</id>
		<title>Device Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3220"/>
		<updated>2010-06-08T19:27:52Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Device interfaces are separate classes that enable devices to participate in more areas of the overall system. Each interface is a sort of contract between the device that inherits from it and related other parts of the system. For example, a device inherits from the execute interface if it wishes to be scheduled and called regularly to execute. Simiarly, a device inherits from the NVRAM interface if it wishes to participate in saving/loading data to the .nv files.&lt;br /&gt;
&lt;br /&gt;
To add an interface to a device, both the device class and device&#039;s configuration class must inherit from the interface&#039;s class and the interface&#039;s configuration class, respectively. Some interfaces are more about configuration than runtime, and others are more about runtime than configuration, but in all cases both interface classes are required.&lt;br /&gt;
&lt;br /&gt;
Since a device is already required to inherit from device_t, this means that you must leverage C++&#039;s &amp;lt;i&amp;gt;multiple inheritance&amp;lt;/i&amp;gt; support in order to add an interface. For example, our configuration class might look like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config,&lt;br /&gt;
                                public device_config_memory_interface,&lt;br /&gt;
                                public device_config_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and our device class like this:&lt;br /&gt;
&lt;br /&gt;
 class example1_device : public device_t,&lt;br /&gt;
                         public device_memory_interface,&lt;br /&gt;
                         public device_nvram_interface&lt;br /&gt;
 {&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Notice first that the &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;device_t&#039;&#039;&#039; classes remain the first classes listed. This is important as they are the real base classes of our device. The interface classes should always be listed afterwards. Also notice that our configuration class and our device class inherit from matching configuration and interface classes.&lt;br /&gt;
&lt;br /&gt;
Each interface has its own demands on the device. Some interfaces, like the sound interface, really don&#039;t require any significant changes. Others, like the NVRAM interface, are pure virtual classes, requiring implementation of one or more methods.&lt;br /&gt;
&lt;br /&gt;
Currently the MAME core defines six standard interfaces:&lt;br /&gt;
&lt;br /&gt;
* The execute interface connects the device to the internal scheduler, and requires implementation of a &#039;&#039;&#039;device_run&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* The memory interface connects the device to the memory system, allowing it to specify one or more address spaces.&lt;br /&gt;
&lt;br /&gt;
* The state interface connects the device to the debugger, enabling display and editing of state during execution from within the register view. It also provides simple indexed accessors for reading/writing state in a standard fashion.&lt;br /&gt;
&lt;br /&gt;
* The NVRAM interface connects the device to the NVRAM read/write process.&lt;br /&gt;
&lt;br /&gt;
* The disassembly interface connects the device to the debugger, enabling disassembly views from within the disassembly window.&lt;br /&gt;
&lt;br /&gt;
* The sound interface connects the device to the sound network, enabling routing of sound from the device to/from other devices.&lt;br /&gt;
&lt;br /&gt;
Details on the interfaces and their requirements are given in the sections below.&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
* Execute&lt;br /&gt;
* Memory&lt;br /&gt;
* State&lt;br /&gt;
* NVRAM&lt;br /&gt;
* Disassembly&lt;br /&gt;
* Sound&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3205</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3205"/>
		<updated>2010-05-26T20:19:52Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Example #1: Simple Device with Static Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
This example is broken into four subsections, describing the configuration structure, the configuration class, the device configuration macros, and then finally the runtime class itself.&lt;br /&gt;
&lt;br /&gt;
==Static Configuration Structure==&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
==Configuration Class==&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
 &lt;br /&gt;
     // internal state&lt;br /&gt;
     int        m_additional_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
* The constructor for the configuration class is kept private. The only way to allocate a new instance of a device configuration is via the static method &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;(). The parameters passed to the constructor in this example are the ones that need to be passed onto the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
Walking through the methods defined in this class one by one, most of them are fairly simple and straightforward. First, the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device_config::example1_device_config(const machine_config &amp;amp;mconfig, const char *tag, &lt;br /&gt;
                 const device_config *owner, UINT32 clock)&lt;br /&gt;
     : device_config(mconfig, static_alloc_device_config, tag, owner, clock),&lt;br /&gt;
       m_additional_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can see, most of the parameters just pass through to the base class. But be sure to initialize all configuration member variables here to ensure they get proper values. We could initialize the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; class here as well, but we&#039;ll wait until the configuration step is complete.&lt;br /&gt;
&lt;br /&gt;
Next up is the static device configuration allocator:&lt;br /&gt;
&lt;br /&gt;
 device_config *example1_device_config::static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
                 const char *tag, const device_config *owner, UINT32 clock)&lt;br /&gt;
 {&lt;br /&gt;
     return global_alloc(example1_device_config(mconfig, tag, owner, clock));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This function is required to be present, as the pointer to this function is used to identify the device type. Given just this function pointer, a configuration object can be constructed, and from there, the device can be created. Note that we need to use &#039;&#039;&#039;global_alloc&#039;&#039;&#039; here because the running_machine has not yet be created (and in fact never may be). Also note that we return a pointer to the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class here, since the machine configuration only knows about the base classes.&lt;br /&gt;
&lt;br /&gt;
The device allocator function follows, and it is also required:&lt;br /&gt;
&lt;br /&gt;
 device_t *example1_device_config::alloc_device(running_machine &amp;amp;machine) const&lt;br /&gt;
 {&lt;br /&gt;
     return auto_alloc(&amp;amp;machine, example1_device(machine, *this));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In contrast to the configuration allocator, which is static and uses &#039;&#039;&#039;global_alloc&#039;&#039;&#039;, the device allocator is a virtual method that uses &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; in order to allocate the device and assign its memory to the provided running machine. When we construct the actual device object, we pass the machine through along with a reference to ourself so that the newly created device can have access to our configuration information.&lt;br /&gt;
&lt;br /&gt;
Once all the device configurations have been created and populated, the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method is called. We override it here to set up our inherited copy of the static configuration structure:&lt;br /&gt;
&lt;br /&gt;
 void example1_device_config::device_config_complete()&lt;br /&gt;
 {&lt;br /&gt;
     // copy static configuration if present&lt;br /&gt;
     if (m_static_config != NULL)&lt;br /&gt;
         *static_cast&amp;lt;example1_device_config_data *&amp;gt;(this) =&lt;br /&gt;
                        *reinterpret_cast&amp;lt;const example1_device_config_data *&amp;gt;(m_static_config);&lt;br /&gt;
 &lt;br /&gt;
     // otherwise, initialize it to defaults&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         m_device_integer_data = DEFAULT_INT_VALUE;&lt;br /&gt;
         m_device_string_data = NULL;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the case where the user specified a pointer to a static configuration data structure, we copy it into ourselves. We use static_cast to find the pointer to where the inherited state lives within our structure and then copy the data pointed to by &#039;&#039;&#039;m_static_config&#039;&#039;&#039;. If no configuration data was provided, we take this opportunity to initialize the inherited configuration structure to default values.&lt;br /&gt;
&lt;br /&gt;
Finally, if the device wishes to provide stronger validation of data -- verified both when starting a game as well as when running MAME with the -validate option -- it can ovverride the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039; method:&lt;br /&gt;
&lt;br /&gt;
 bool example1_device_config::device_validity_check(const game_driver &amp;amp;driver) const&lt;br /&gt;
 {&lt;br /&gt;
     bool error = false;&lt;br /&gt;
 &lt;br /&gt;
     // sanity check configuration&lt;br /&gt;
     if (m_device_integer_value &amp;lt; 0)&lt;br /&gt;
     {&lt;br /&gt;
          mame_printf_error(&amp;quot;%s: %s device &#039;%s&#039; has invalid integer parameter\n&amp;quot;, &lt;br /&gt;
                            driver.source_file, driver.name, tag());&lt;br /&gt;
          error = true;&lt;br /&gt;
     }&lt;br /&gt;
     return error;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method should examing the configuration data, output friendly errors and warnings, and return true if a fatal error was detected.&lt;br /&gt;
&lt;br /&gt;
==Configuration Macros==&lt;br /&gt;
&lt;br /&gt;
Now we need to declare how to reference the device from a machine configuration. This is done via special tokenizing macros:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_ADD(&amp;quot;tag&amp;quot;, DEVICE_TYPE, device_clock)&lt;br /&gt;
 MDRV_DEVICE_REPLACE(&amp;quot;tag&amp;quot;, DEVICE_TYPE, device_clock)&lt;br /&gt;
&lt;br /&gt;
So the first thing we need to define is our ALL_CAPS DEVICE_TYPE. As mentioned previously, the device type is simply a pointer to the static &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;() method, so it should be defined like so:&lt;br /&gt;
&lt;br /&gt;
 static const device_type EXAMPLE1 = example1_device_config::static_alloc_device_config;&lt;br /&gt;
&lt;br /&gt;
Although this is all that is required at a minimum, in general it is considered a good idea to provide your own set of MDRV macros that are specific to your device. By defining our macros, we can more precisely guide the user to ensure all data is properly specified. Let&#039;s say for example that our static configuration is required (i.e., it is invalid to not specify anything). Using the raw macros, a driver writer would declare an instance of our device like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_ADD(&amp;quot;tag&amp;quot;, EXAMPLE1, 0)&lt;br /&gt;
 MDRV_DEVICE_CONFIG(local_structure)&lt;br /&gt;
&lt;br /&gt;
Given this, you can see that it would be easy to forget the second line and leave a device with no configuration data. Also, the user is forced to specify a dummy clock, even though our device doesn&#039;t need one. Instead, let&#039;s define our own macro for adding an EXAMPLE1 device, like so:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_EXAMPLE1_ADD(_tag, _config) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, EXAMPLE1, 0) \&lt;br /&gt;
     MDRV_DEVICE_CONFIG(_config)&lt;br /&gt;
&lt;br /&gt;
and then the equivalent declaration becomes:&lt;br /&gt;
&lt;br /&gt;
 MDRV_EXAMPLE1_ADD(&amp;quot;tag&amp;quot;, local_structure)&lt;br /&gt;
&lt;br /&gt;
By doing this, we get to provide a cleaner interface for declaration, and at the same time we ensure that a required parameter is specified.&lt;br /&gt;
&lt;br /&gt;
==Runtime Class==&lt;br /&gt;
&lt;br /&gt;
Next we move on to the runtime device class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device : public device_t&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device_config;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device(running_machine &amp;amp;machine, const example1_device_config &amp;amp;config);&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // any publically acessible interfaces needed for runtime&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides (none are required, but these are common)&lt;br /&gt;
     virtual void device_start();&lt;br /&gt;
     virtual void device_reset();&lt;br /&gt;
 &lt;br /&gt;
     // internal device state goes here&lt;br /&gt;
     const example1_device_config &amp;amp;m_config;&lt;br /&gt;
     int                           m_device_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Going through the class definition, there are some similar patterns to the corresponding device configuration class:&lt;br /&gt;
&lt;br /&gt;
* Again, we derive from a common base class, in this case the &#039;&#039;&#039;device_t&#039;&#039;&#039; class. However, unlike the configuration class, we just have simple single inheritance here, since we don&#039;t need the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct.&lt;br /&gt;
&lt;br /&gt;
* We make our configuration class our friend, just as they made us their friend. Really, you should imagine these two classes as two halves of the entire device.&lt;br /&gt;
&lt;br /&gt;
* As with the configuration class, our constructor is kept private. A device should only be allocated via the corresponding configuration class&#039;s &#039;&#039;&#039;alloc_device&#039;&#039;&#039;() method. Since our configuration class is our friend, it can still allocate us.&lt;br /&gt;
&lt;br /&gt;
* There are no standard methods that need to be public in the runtime device. However, it is quite likely you will need some in order to interact with it (read/write handlers fall into this category, for example).&lt;br /&gt;
&lt;br /&gt;
* This example overrides two device-specific notification methods, one which is called at device start time (after all devices are constructed), and one which is called at reset time. These are optional, though common, to override.&lt;br /&gt;
&lt;br /&gt;
* At the bottom you&#039;ll see a reference to our configuration class. This is kept to enable easy access to the configuration data.&lt;br /&gt;
&lt;br /&gt;
Looking at each of the methods above in a little detail, we first encounter the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device::example1_device(running_machine &amp;amp;machine, const example1_device_config &amp;amp;config)&lt;br /&gt;
     : device_t(machine, config),&lt;br /&gt;
       m_config(config),&lt;br /&gt;
       m_device_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Here we initialize our parent class by passing down the reference to the running_machine and our configuration. We also stash a reference to our configuration into the m_config variable for later use, and we reset all our internal state variables to something well-defined. Note that we don&#039;t generally do much initialization in the constructor; that work is preferred to live in the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Speaking of which...&lt;br /&gt;
&lt;br /&gt;
 example1_device::device_start()&lt;br /&gt;
 {&lt;br /&gt;
     // initialize state from configuration&lt;br /&gt;
     // locate any other devices&lt;br /&gt;
     //    if other devices not ready, throw device_missing_dependencies()&lt;br /&gt;
     // register for any save state&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Okay, not much meat in the implementation above, but there are a number of things expected of a device during &#039;&#039;&#039;device_start&#039;&#039;&#039;() time, including consumption of the configuration, identification of related devices, and set up for save states. If a related device is located (at this point all devices are constructed) but it hasn&#039;t yet been started, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039;() exception and your &#039;&#039;&#039;device_start&#039;&#039;&#039;() will be queued to the end of the list to be called again later.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
 example1_device::device_reset()&lt;br /&gt;
 {&lt;br /&gt;
     // reset internal state to well-defined values&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method is there to enable resetting a device&#039;s state in the event of a requested reset.&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3204</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3204"/>
		<updated>2010-05-26T20:18:08Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Configuration Macros */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
This example is broken into two subsections, describing the configuration class and then the runtime class.&lt;br /&gt;
&lt;br /&gt;
==Static Configuration Structure==&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
==Configuration Class==&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
 &lt;br /&gt;
     // internal state&lt;br /&gt;
     int        m_additional_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
* The constructor for the configuration class is kept private. The only way to allocate a new instance of a device configuration is via the static method &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;(). The parameters passed to the constructor in this example are the ones that need to be passed onto the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
Walking through the methods defined in this class one by one, most of them are fairly simple and straightforward. First, the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device_config::example1_device_config(const machine_config &amp;amp;mconfig, const char *tag, &lt;br /&gt;
                 const device_config *owner, UINT32 clock)&lt;br /&gt;
     : device_config(mconfig, static_alloc_device_config, tag, owner, clock),&lt;br /&gt;
       m_additional_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can see, most of the parameters just pass through to the base class. But be sure to initialize all configuration member variables here to ensure they get proper values. We could initialize the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; class here as well, but we&#039;ll wait until the configuration step is complete.&lt;br /&gt;
&lt;br /&gt;
Next up is the static device configuration allocator:&lt;br /&gt;
&lt;br /&gt;
 device_config *example1_device_config::static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
                 const char *tag, const device_config *owner, UINT32 clock)&lt;br /&gt;
 {&lt;br /&gt;
     return global_alloc(example1_device_config(mconfig, tag, owner, clock));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This function is required to be present, as the pointer to this function is used to identify the device type. Given just this function pointer, a configuration object can be constructed, and from there, the device can be created. Note that we need to use &#039;&#039;&#039;global_alloc&#039;&#039;&#039; here because the running_machine has not yet be created (and in fact never may be). Also note that we return a pointer to the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class here, since the machine configuration only knows about the base classes.&lt;br /&gt;
&lt;br /&gt;
The device allocator function follows, and it is also required:&lt;br /&gt;
&lt;br /&gt;
 device_t *example1_device_config::alloc_device(running_machine &amp;amp;machine) const&lt;br /&gt;
 {&lt;br /&gt;
     return auto_alloc(&amp;amp;machine, example1_device(machine, *this));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In contrast to the configuration allocator, which is static and uses &#039;&#039;&#039;global_alloc&#039;&#039;&#039;, the device allocator is a virtual method that uses &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; in order to allocate the device and assign its memory to the provided running machine. When we construct the actual device object, we pass the machine through along with a reference to ourself so that the newly created device can have access to our configuration information.&lt;br /&gt;
&lt;br /&gt;
Once all the device configurations have been created and populated, the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method is called. We override it here to set up our inherited copy of the static configuration structure:&lt;br /&gt;
&lt;br /&gt;
 void example1_device_config::device_config_complete()&lt;br /&gt;
 {&lt;br /&gt;
     // copy static configuration if present&lt;br /&gt;
     if (m_static_config != NULL)&lt;br /&gt;
         *static_cast&amp;lt;example1_device_config_data *&amp;gt;(this) =&lt;br /&gt;
                        *reinterpret_cast&amp;lt;const example1_device_config_data *&amp;gt;(m_static_config);&lt;br /&gt;
 &lt;br /&gt;
     // otherwise, initialize it to defaults&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         m_device_integer_data = DEFAULT_INT_VALUE;&lt;br /&gt;
         m_device_string_data = NULL;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the case where the user specified a pointer to a static configuration data structure, we copy it into ourselves. We use static_cast to find the pointer to where the inherited state lives within our structure and then copy the data pointed to by &#039;&#039;&#039;m_static_config&#039;&#039;&#039;. If no configuration data was provided, we take this opportunity to initialize the inherited configuration structure to default values.&lt;br /&gt;
&lt;br /&gt;
Finally, if the device wishes to provide stronger validation of data -- verified both when starting a game as well as when running MAME with the -validate option -- it can ovverride the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039; method:&lt;br /&gt;
&lt;br /&gt;
 bool example1_device_config::device_validity_check(const game_driver &amp;amp;driver) const&lt;br /&gt;
 {&lt;br /&gt;
     bool error = false;&lt;br /&gt;
 &lt;br /&gt;
     // sanity check configuration&lt;br /&gt;
     if (m_device_integer_value &amp;lt; 0)&lt;br /&gt;
     {&lt;br /&gt;
          mame_printf_error(&amp;quot;%s: %s device &#039;%s&#039; has invalid integer parameter\n&amp;quot;, &lt;br /&gt;
                            driver.source_file, driver.name, tag());&lt;br /&gt;
          error = true;&lt;br /&gt;
     }&lt;br /&gt;
     return error;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method should examing the configuration data, output friendly errors and warnings, and return true if a fatal error was detected.&lt;br /&gt;
&lt;br /&gt;
==Configuration Macros==&lt;br /&gt;
&lt;br /&gt;
Now we need to declare how to reference the device from a machine configuration. This is done via special tokenizing macros:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_ADD(&amp;quot;tag&amp;quot;, DEVICE_TYPE, device_clock)&lt;br /&gt;
 MDRV_DEVICE_REPLACE(&amp;quot;tag&amp;quot;, DEVICE_TYPE, device_clock)&lt;br /&gt;
&lt;br /&gt;
So the first thing we need to define is our ALL_CAPS DEVICE_TYPE. As mentioned previously, the device type is simply a pointer to the static &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;() method, so it should be defined like so:&lt;br /&gt;
&lt;br /&gt;
 static const device_type EXAMPLE1 = example1_device_config::static_alloc_device_config;&lt;br /&gt;
&lt;br /&gt;
Although this is all that is required at a minimum, in general it is considered a good idea to provide your own set of MDRV macros that are specific to your device. By defining our macros, we can more precisely guide the user to ensure all data is properly specified. Let&#039;s say for example that our static configuration is required (i.e., it is invalid to not specify anything). Using the raw macros, a driver writer would declare an instance of our device like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_ADD(&amp;quot;tag&amp;quot;, EXAMPLE1, 0)&lt;br /&gt;
 MDRV_DEVICE_CONFIG(local_structure)&lt;br /&gt;
&lt;br /&gt;
Given this, you can see that it would be easy to forget the second line and leave a device with no configuration data. Also, the user is forced to specify a dummy clock, even though our device doesn&#039;t need one. Instead, let&#039;s define our own macro for adding an EXAMPLE1 device, like so:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_EXAMPLE1_ADD(_tag, _config) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, EXAMPLE1, 0) \&lt;br /&gt;
     MDRV_DEVICE_CONFIG(_config)&lt;br /&gt;
&lt;br /&gt;
and then the equivalent declaration becomes:&lt;br /&gt;
&lt;br /&gt;
 MDRV_EXAMPLE1_ADD(&amp;quot;tag&amp;quot;, local_structure)&lt;br /&gt;
&lt;br /&gt;
By doing this, we get to provide a cleaner interface for declaration, and at the same time we ensure that a required parameter is specified.&lt;br /&gt;
&lt;br /&gt;
==Runtime Class==&lt;br /&gt;
&lt;br /&gt;
Next we move on to the runtime device class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device : public device_t&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device_config;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device(running_machine &amp;amp;machine, const example1_device_config &amp;amp;config);&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // any publically acessible interfaces needed for runtime&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides (none are required, but these are common)&lt;br /&gt;
     virtual void device_start();&lt;br /&gt;
     virtual void device_reset();&lt;br /&gt;
 &lt;br /&gt;
     // internal device state goes here&lt;br /&gt;
     const example1_device_config &amp;amp;m_config;&lt;br /&gt;
     int                           m_device_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Going through the class definition, there are some similar patterns to the corresponding device configuration class:&lt;br /&gt;
&lt;br /&gt;
* Again, we derive from a common base class, in this case the &#039;&#039;&#039;device_t&#039;&#039;&#039; class. However, unlike the configuration class, we just have simple single inheritance here, since we don&#039;t need the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct.&lt;br /&gt;
&lt;br /&gt;
* We make our configuration class our friend, just as they made us their friend. Really, you should imagine these two classes as two halves of the entire device.&lt;br /&gt;
&lt;br /&gt;
* As with the configuration class, our constructor is kept private. A device should only be allocated via the corresponding configuration class&#039;s &#039;&#039;&#039;alloc_device&#039;&#039;&#039;() method. Since our configuration class is our friend, it can still allocate us.&lt;br /&gt;
&lt;br /&gt;
* There are no standard methods that need to be public in the runtime device. However, it is quite likely you will need some in order to interact with it (read/write handlers fall into this category, for example).&lt;br /&gt;
&lt;br /&gt;
* This example overrides two device-specific notification methods, one which is called at device start time (after all devices are constructed), and one which is called at reset time. These are optional, though common, to override.&lt;br /&gt;
&lt;br /&gt;
* At the bottom you&#039;ll see a reference to our configuration class. This is kept to enable easy access to the configuration data.&lt;br /&gt;
&lt;br /&gt;
Looking at each of the methods above in a little detail, we first encounter the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device::example1_device(running_machine &amp;amp;machine, const example1_device_config &amp;amp;config)&lt;br /&gt;
     : device_t(machine, config),&lt;br /&gt;
       m_config(config),&lt;br /&gt;
       m_device_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Here we initialize our parent class by passing down the reference to the running_machine and our configuration. We also stash a reference to our configuration into the m_config variable for later use, and we reset all our internal state variables to something well-defined. Note that we don&#039;t generally do much initialization in the constructor; that work is preferred to live in the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Speaking of which...&lt;br /&gt;
&lt;br /&gt;
 example1_device::device_start()&lt;br /&gt;
 {&lt;br /&gt;
     // initialize state from configuration&lt;br /&gt;
     // locate any other devices&lt;br /&gt;
     //    if other devices not ready, throw device_missing_dependencies()&lt;br /&gt;
     // register for any save state&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Okay, not much meat in the implementation above, but there are a number of things expected of a device during &#039;&#039;&#039;device_start&#039;&#039;&#039;() time, including consumption of the configuration, identification of related devices, and set up for save states. If a related device is located (at this point all devices are constructed) but it hasn&#039;t yet been started, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039;() exception and your &#039;&#039;&#039;device_start&#039;&#039;&#039;() will be queued to the end of the list to be called again later.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
 example1_device::device_reset()&lt;br /&gt;
 {&lt;br /&gt;
     // reset internal state to well-defined values&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method is there to enable resetting a device&#039;s state in the event of a requested reset.&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3203</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3203"/>
		<updated>2010-05-26T20:17:38Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Example #1: Simple Device with Static Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
This example is broken into two subsections, describing the configuration class and then the runtime class.&lt;br /&gt;
&lt;br /&gt;
==Static Configuration Structure==&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
==Configuration Class==&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
 &lt;br /&gt;
     // internal state&lt;br /&gt;
     int        m_additional_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
* The constructor for the configuration class is kept private. The only way to allocate a new instance of a device configuration is via the static method &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;(). The parameters passed to the constructor in this example are the ones that need to be passed onto the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
Walking through the methods defined in this class one by one, most of them are fairly simple and straightforward. First, the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device_config::example1_device_config(const machine_config &amp;amp;mconfig, const char *tag, &lt;br /&gt;
                 const device_config *owner, UINT32 clock)&lt;br /&gt;
     : device_config(mconfig, static_alloc_device_config, tag, owner, clock),&lt;br /&gt;
       m_additional_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can see, most of the parameters just pass through to the base class. But be sure to initialize all configuration member variables here to ensure they get proper values. We could initialize the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; class here as well, but we&#039;ll wait until the configuration step is complete.&lt;br /&gt;
&lt;br /&gt;
Next up is the static device configuration allocator:&lt;br /&gt;
&lt;br /&gt;
 device_config *example1_device_config::static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
                 const char *tag, const device_config *owner, UINT32 clock)&lt;br /&gt;
 {&lt;br /&gt;
     return global_alloc(example1_device_config(mconfig, tag, owner, clock));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This function is required to be present, as the pointer to this function is used to identify the device type. Given just this function pointer, a configuration object can be constructed, and from there, the device can be created. Note that we need to use &#039;&#039;&#039;global_alloc&#039;&#039;&#039; here because the running_machine has not yet be created (and in fact never may be). Also note that we return a pointer to the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class here, since the machine configuration only knows about the base classes.&lt;br /&gt;
&lt;br /&gt;
The device allocator function follows, and it is also required:&lt;br /&gt;
&lt;br /&gt;
 device_t *example1_device_config::alloc_device(running_machine &amp;amp;machine) const&lt;br /&gt;
 {&lt;br /&gt;
     return auto_alloc(&amp;amp;machine, example1_device(machine, *this));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In contrast to the configuration allocator, which is static and uses &#039;&#039;&#039;global_alloc&#039;&#039;&#039;, the device allocator is a virtual method that uses &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; in order to allocate the device and assign its memory to the provided running machine. When we construct the actual device object, we pass the machine through along with a reference to ourself so that the newly created device can have access to our configuration information.&lt;br /&gt;
&lt;br /&gt;
Once all the device configurations have been created and populated, the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method is called. We override it here to set up our inherited copy of the static configuration structure:&lt;br /&gt;
&lt;br /&gt;
 void example1_device_config::device_config_complete()&lt;br /&gt;
 {&lt;br /&gt;
     // copy static configuration if present&lt;br /&gt;
     if (m_static_config != NULL)&lt;br /&gt;
         *static_cast&amp;lt;example1_device_config_data *&amp;gt;(this) =&lt;br /&gt;
                        *reinterpret_cast&amp;lt;const example1_device_config_data *&amp;gt;(m_static_config);&lt;br /&gt;
 &lt;br /&gt;
     // otherwise, initialize it to defaults&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         m_device_integer_data = DEFAULT_INT_VALUE;&lt;br /&gt;
         m_device_string_data = NULL;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the case where the user specified a pointer to a static configuration data structure, we copy it into ourselves. We use static_cast to find the pointer to where the inherited state lives within our structure and then copy the data pointed to by &#039;&#039;&#039;m_static_config&#039;&#039;&#039;. If no configuration data was provided, we take this opportunity to initialize the inherited configuration structure to default values.&lt;br /&gt;
&lt;br /&gt;
Finally, if the device wishes to provide stronger validation of data -- verified both when starting a game as well as when running MAME with the -validate option -- it can ovverride the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039; method:&lt;br /&gt;
&lt;br /&gt;
 bool example1_device_config::device_validity_check(const game_driver &amp;amp;driver) const&lt;br /&gt;
 {&lt;br /&gt;
     bool error = false;&lt;br /&gt;
 &lt;br /&gt;
     // sanity check configuration&lt;br /&gt;
     if (m_device_integer_value &amp;lt; 0)&lt;br /&gt;
     {&lt;br /&gt;
          mame_printf_error(&amp;quot;%s: %s device &#039;%s&#039; has invalid integer parameter\n&amp;quot;, &lt;br /&gt;
                            driver.source_file, driver.name, tag());&lt;br /&gt;
          error = true;&lt;br /&gt;
     }&lt;br /&gt;
     return error;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method should examing the configuration data, output friendly errors and warnings, and return true if a fatal error was detected.&lt;br /&gt;
&lt;br /&gt;
==Configuration Macros==&lt;br /&gt;
&lt;br /&gt;
Now we need to declare how to reference the device from a machine configuration. This is done via special tokenizing macros:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_ADD(&amp;quot;tag&amp;quot;, DEVICE_TYPE, device_clock)&lt;br /&gt;
 MDRV_DEVICE_REPLACE(&amp;quot;tag&amp;quot;, DEVICE_TYPE, device_clock)&lt;br /&gt;
&lt;br /&gt;
So the first thing we need to define is our ALL_CAPS DEVICE_TYPE. As mentiond previously, the device type is simply a pointer to the static &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;() method, so it should be defined like so:&lt;br /&gt;
&lt;br /&gt;
 static const device_type EXAMPLE1 = example1_device_config::static_alloc_device_config;&lt;br /&gt;
&lt;br /&gt;
Although this is all that is required at a minimum, in general it is considered a good idea to provide your own set of MDRV macros that are specific to your device. By defining our macros, we can more precisely guide the user to ensure all data is properly specified. Let&#039;s say for example that our static configuration is required (i.e., it is invalid to not specify anything). Using the raw macros, a driver writer would declare an instance of our device like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_ADD(&amp;quot;tag&amp;quot;, EXAMPLE1, 0)&lt;br /&gt;
 MDRV_DEVICE_CONFIG(local_structure)&lt;br /&gt;
&lt;br /&gt;
Given this, you can see that it would be easy to forget the second line and leave a device with no configuration data. Also, the user is forced to specify a dummy clock, even though our device doesn&#039;t need one. Instead, let&#039;s define our own macro for adding an EXAMPLE1 device, like so:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_EXAMPLE1_ADD(_tag, _config) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, EXAMPLE1, 0) \&lt;br /&gt;
     MDRV_DEVICE_CONFIG(_config)&lt;br /&gt;
&lt;br /&gt;
and then the equivalent declaration becomes:&lt;br /&gt;
&lt;br /&gt;
 MDRV_EXAMPLE1_ADD(&amp;quot;tag&amp;quot;, local_structure)&lt;br /&gt;
&lt;br /&gt;
By doing this, we get to provide a cleaner interface for declaration, and at the same time we ensure that a required parameter is specified.&lt;br /&gt;
&lt;br /&gt;
==Runtime Class==&lt;br /&gt;
&lt;br /&gt;
Next we move on to the runtime device class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device : public device_t&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device_config;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device(running_machine &amp;amp;machine, const example1_device_config &amp;amp;config);&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // any publically acessible interfaces needed for runtime&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides (none are required, but these are common)&lt;br /&gt;
     virtual void device_start();&lt;br /&gt;
     virtual void device_reset();&lt;br /&gt;
 &lt;br /&gt;
     // internal device state goes here&lt;br /&gt;
     const example1_device_config &amp;amp;m_config;&lt;br /&gt;
     int                           m_device_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Going through the class definition, there are some similar patterns to the corresponding device configuration class:&lt;br /&gt;
&lt;br /&gt;
* Again, we derive from a common base class, in this case the &#039;&#039;&#039;device_t&#039;&#039;&#039; class. However, unlike the configuration class, we just have simple single inheritance here, since we don&#039;t need the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct.&lt;br /&gt;
&lt;br /&gt;
* We make our configuration class our friend, just as they made us their friend. Really, you should imagine these two classes as two halves of the entire device.&lt;br /&gt;
&lt;br /&gt;
* As with the configuration class, our constructor is kept private. A device should only be allocated via the corresponding configuration class&#039;s &#039;&#039;&#039;alloc_device&#039;&#039;&#039;() method. Since our configuration class is our friend, it can still allocate us.&lt;br /&gt;
&lt;br /&gt;
* There are no standard methods that need to be public in the runtime device. However, it is quite likely you will need some in order to interact with it (read/write handlers fall into this category, for example).&lt;br /&gt;
&lt;br /&gt;
* This example overrides two device-specific notification methods, one which is called at device start time (after all devices are constructed), and one which is called at reset time. These are optional, though common, to override.&lt;br /&gt;
&lt;br /&gt;
* At the bottom you&#039;ll see a reference to our configuration class. This is kept to enable easy access to the configuration data.&lt;br /&gt;
&lt;br /&gt;
Looking at each of the methods above in a little detail, we first encounter the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device::example1_device(running_machine &amp;amp;machine, const example1_device_config &amp;amp;config)&lt;br /&gt;
     : device_t(machine, config),&lt;br /&gt;
       m_config(config),&lt;br /&gt;
       m_device_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Here we initialize our parent class by passing down the reference to the running_machine and our configuration. We also stash a reference to our configuration into the m_config variable for later use, and we reset all our internal state variables to something well-defined. Note that we don&#039;t generally do much initialization in the constructor; that work is preferred to live in the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Speaking of which...&lt;br /&gt;
&lt;br /&gt;
 example1_device::device_start()&lt;br /&gt;
 {&lt;br /&gt;
     // initialize state from configuration&lt;br /&gt;
     // locate any other devices&lt;br /&gt;
     //    if other devices not ready, throw device_missing_dependencies()&lt;br /&gt;
     // register for any save state&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Okay, not much meat in the implementation above, but there are a number of things expected of a device during &#039;&#039;&#039;device_start&#039;&#039;&#039;() time, including consumption of the configuration, identification of related devices, and set up for save states. If a related device is located (at this point all devices are constructed) but it hasn&#039;t yet been started, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039;() exception and your &#039;&#039;&#039;device_start&#039;&#039;&#039;() will be queued to the end of the list to be called again later.&lt;br /&gt;
&lt;br /&gt;
Similarly,&lt;br /&gt;
&lt;br /&gt;
 example1_device::device_reset()&lt;br /&gt;
 {&lt;br /&gt;
     // reset internal state to well-defined values&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method is there to enable resetting a device&#039;s state in the event of a requested reset.&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3202</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3202"/>
		<updated>2010-05-25T05:07:57Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Example #1: Simple Device with Static Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
 &lt;br /&gt;
     // internal state&lt;br /&gt;
     int        m_additional_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
* If the configuration requires a destructor, then you will either need to &lt;br /&gt;
&lt;br /&gt;
* The constructor for the configuration class is kept private. The only way to allocate a new instance of a device configuration is via the static method &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;(). The parameters passed to the constructor in this example are the ones that need to be passed onto the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
Walking through the methods defined in this class one by one, most of them are fairly simple and straightforward. First, the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device_config::example1_device_config(const machine_config &amp;amp;mconfig, const char *tag, &lt;br /&gt;
                 const device_config *owner, UINT32 clock)&lt;br /&gt;
     : device_config(mconfig, static_alloc_device_config, tag, owner, clock),&lt;br /&gt;
       m_additional_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can see, most of the parameters just pass through to the base class. But be sure to initialize all configuration member variables here to ensure they get proper values. We could initialize the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; class here as well, but we&#039;ll wait until the configuration step is complete.&lt;br /&gt;
&lt;br /&gt;
Next up is the static device configuration allocator:&lt;br /&gt;
&lt;br /&gt;
 device_config *example1_device_config::static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
                 const char *tag, const device_config *owner, UINT32 clock)&lt;br /&gt;
 {&lt;br /&gt;
     return global_alloc(example1_device_config(mconfig, tag, owner, clock));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This function is required to be present, as the pointer to this function is used to identify the device type. Given just this function pointer, a configuration object can be constructed, and from there, the device can be created. Note that we need to use &#039;&#039;&#039;global_alloc&#039;&#039;&#039; here because the running_machine has not yet be created (and in fact never may be). Also note that we return a pointer to the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class here, since the machine configuration only knows about the base classes.&lt;br /&gt;
&lt;br /&gt;
The device allocator function follows, and it is also required:&lt;br /&gt;
&lt;br /&gt;
 device_t *example1_device_config::alloc_device(running_machine &amp;amp;machine) const&lt;br /&gt;
 {&lt;br /&gt;
     return auto_alloc(&amp;amp;machine, example1_device(machine, *this));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In contrast to the configuration allocator, which is static and uses &#039;&#039;&#039;global_alloc&#039;&#039;&#039;, the device allocator is a virtual method that uses &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; in order to allocate the device and assign its memory to the provided running machine. When we construct the actual device object, we pass the machine through along with a reference to ourself so that the newly created device can have access to our configuration information.&lt;br /&gt;
&lt;br /&gt;
Once all the device configurations have been created and populated, the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method is called. We override it here to set up our inherited copy of the static configuration structure:&lt;br /&gt;
&lt;br /&gt;
 void example1_device_config::device_config_complete()&lt;br /&gt;
 {&lt;br /&gt;
     // copy static configuration if present&lt;br /&gt;
     if (m_static_config != NULL)&lt;br /&gt;
         *static_cast&amp;lt;example1_device_config_data *&amp;gt;(this) =&lt;br /&gt;
                        *reinterpret_cast&amp;lt;const example1_device_config_data *&amp;gt;(m_static_config);&lt;br /&gt;
 &lt;br /&gt;
     // otherwise, initialize it to defaults&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         m_device_integer_data = DEFAULT_INT_VALUE;&lt;br /&gt;
         m_device_string_data = NULL;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the case where the user specified a pointer to a static configuration data structure, we copy it into ourselves. We use static_cast to find the pointer to where the inherited state lives within our structure and then copy the data pointed to by &#039;&#039;&#039;m_static_config&#039;&#039;&#039;. If no configuration data was provided, we take this opportunity to initialize the inherited configuration structure to default values.&lt;br /&gt;
&lt;br /&gt;
Finally, if the device wishes to provide stronger validation of data -- verified both when starting a game as well as when running MAME with the -validate option -- it can ovverride the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039; method:&lt;br /&gt;
&lt;br /&gt;
 bool example1_device_config::device_validity_check(const game_driver &amp;amp;driver) const&lt;br /&gt;
 {&lt;br /&gt;
     bool error = false;&lt;br /&gt;
 &lt;br /&gt;
     // sanity check configuration&lt;br /&gt;
     if (m_device_integer_value &amp;lt; 0)&lt;br /&gt;
     {&lt;br /&gt;
          mame_printf_error(&amp;quot;%s: %s device &#039;%s&#039; has invalid integer parameter\n&amp;quot;, &lt;br /&gt;
                            driver.source_file, driver.name, tag());&lt;br /&gt;
          error = true;&lt;br /&gt;
     }&lt;br /&gt;
     return error;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method should examing the configuration data, output friendly errors and warnings, and return true if a fatal error was detected.&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3201</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3201"/>
		<updated>2010-05-24T20:26:25Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Example #1: Simple Device with Static Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
 public:&lt;br /&gt;
     virtual ~example1_device_config();&lt;br /&gt;
 &lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
 &lt;br /&gt;
     // internal state&lt;br /&gt;
     int        m_additional_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
* The constructor for the configuration class is kept private. The only way to allocate a new instance of a device configuration is via the static method &#039;&#039;&#039;static_alloc_device_config&#039;&#039;&#039;(). The parameters passed to the constructor in this example are the ones that need to be passed onto the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
* Note that the destructor is virtual. If you fail to do this you will end up partially destructing objects.&lt;br /&gt;
&lt;br /&gt;
Walking through the methods defined in this class one by one, most of them are fairly simple and straightforward. First, the constructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device_config::example1_device_config(const machine_config &amp;amp;mconfig, const char *tag, &lt;br /&gt;
                 const device_config *owner, UINT32 clock)&lt;br /&gt;
     : device_config(mconfig, static_alloc_device_config, tag, owner, clock),&lt;br /&gt;
       m_additional_state(0)&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As you can see, most of the parameters just pass through to the base class. But be sure to initialize all configuration member variables here to ensure they get proper values. We could initialize the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; class here as well, but we&#039;ll wait until the configuration step is complete.&lt;br /&gt;
&lt;br /&gt;
Next, the destructor:&lt;br /&gt;
&lt;br /&gt;
 example1_device_config::~example1_device_config()&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If we had allocated memory in the constructor or elsewhere during configuration, now would be the time to free it. This example doesn&#039;t do that, so our destructor is empty.&lt;br /&gt;
&lt;br /&gt;
Next up is the static device configuration allocator:&lt;br /&gt;
&lt;br /&gt;
 device_config *example1_device_config::static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
                 const char *tag, const device_config *owner, UINT32 clock)&lt;br /&gt;
 {&lt;br /&gt;
     return global_alloc(example1_device_config(mconfig, tag, owner, clock));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This function is required to be present, as the pointer to this function is used to identify the device type. Given just this function pointer, a configuration object can be constructed, and from there, the device can be created. Note that we need to use &#039;&#039;&#039;global_alloc&#039;&#039;&#039; here because the running_machine has not yet be created (and in fact never may be). Also note that we return a pointer to the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class here, since the machine configuration only knows about the base classes.&lt;br /&gt;
&lt;br /&gt;
The device allocator function follows, and it is also required:&lt;br /&gt;
&lt;br /&gt;
 device_t *example1_device_config::alloc_device(running_machine &amp;amp;machine) const&lt;br /&gt;
 {&lt;br /&gt;
     return auto_alloc(&amp;amp;machine, example1_device(machine, *this));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In contrast to the configuration allocator, which is static and uses &#039;&#039;&#039;global_alloc&#039;&#039;&#039;, the device allocator is a virtual method that uses &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; in order to allocate the device and assign its memory to the provided running machine. When we construct the actual device object, we pass the machine through along with a reference to ourself so that the newly created device can have access to our configuration information.&lt;br /&gt;
&lt;br /&gt;
Once all the device configurations have been created and populated, the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method is called. We override it here to set up our inherited copy of the static configuration structure:&lt;br /&gt;
&lt;br /&gt;
 void example1_device_config::device_config_complete()&lt;br /&gt;
 {&lt;br /&gt;
     // copy static configuration if present&lt;br /&gt;
     if (m_static_config != NULL)&lt;br /&gt;
         *static_cast&amp;lt;example1_device_config_data *&amp;gt;(this) =&lt;br /&gt;
                        *reinterpret_cast&amp;lt;const example1_device_config_data *&amp;gt;(m_static_config);&lt;br /&gt;
 &lt;br /&gt;
     // otherwise, initialize it to defaults&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         m_device_integer_data = DEFAULT_INT_VALUE;&lt;br /&gt;
         m_device_string_data = NULL;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In the case where the user specified a pointer to a static configuration data structure, we copy it into ourselves. We use static_cast to find the pointer to where the inherited state lives within our structure and then copy the data pointed to by &#039;&#039;&#039;m_static_config&#039;&#039;&#039;. If no configuration data was provided, we take this opportunity to initialize the inherited configuration structure to default values.&lt;br /&gt;
&lt;br /&gt;
Finally, if the device wishes to provide stronger validation of data -- verified both when starting a game as well as when running MAME with the -validate option -- it can ovverride the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039; method:&lt;br /&gt;
&lt;br /&gt;
 bool example1_device_config::device_validity_check(const game_driver &amp;amp;driver) const&lt;br /&gt;
 {&lt;br /&gt;
     bool error = false;&lt;br /&gt;
 &lt;br /&gt;
     // sanity check configuration&lt;br /&gt;
     if (m_device_integer_value &amp;lt; 0)&lt;br /&gt;
     {&lt;br /&gt;
          mame_printf_error(&amp;quot;%s: %s device &#039;%s&#039; has invalid integer parameter\n&amp;quot;, &lt;br /&gt;
                            driver.source_file, driver.name, tag());&lt;br /&gt;
          error = true;&lt;br /&gt;
     }&lt;br /&gt;
     return error;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method should examing the configuration data, output friendly errors and warnings, and return true if a fatal error was detected.&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3200</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3200"/>
		<updated>2010-05-24T18:39:42Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Example #1: Simple Device with Static Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual ~example1_device_config();&lt;br /&gt;
 &lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
 &lt;br /&gt;
     // internal state&lt;br /&gt;
     int        m_additional_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
(more later)&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3199</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3199"/>
		<updated>2010-05-21T21:58:53Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Example #1: Simple Device with Static Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     DISABLE_COPYING(example1_device_config);&lt;br /&gt;
 &lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual ~example1_device_config();&lt;br /&gt;
 &lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
 &lt;br /&gt;
     // internal state&lt;br /&gt;
     int        m_additional_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you see the DISABLE_COPYING macro; this just defines a standard copy constructor and copy operator as private so that you can&#039;t accidentally assign a device and implicitly make a copy (which would be bad)&lt;br /&gt;
&lt;br /&gt;
* You&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
(more later)&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3198</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3198"/>
		<updated>2010-05-21T21:58:38Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Example #1: Simple Device with Static Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     DISABLE_COPYING(example1_device_config);&lt;br /&gt;
 &lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual ~example1_device_config();&lt;br /&gt;
 &lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
&lt;br /&gt;
     // internal state&lt;br /&gt;
     int        m_additional_state;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you see the DISABLE_COPYING macro; this just defines a standard copy constructor and copy operator as private so that you can&#039;t accidentally assign a device and implicitly make a copy (which would be bad)&lt;br /&gt;
&lt;br /&gt;
* You&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
(more later)&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3197</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3197"/>
		<updated>2010-05-21T20:08:25Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Example #1: Simple Device with Static Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     DISABLE_COPYING(example1_device_config );&lt;br /&gt;
 &lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
 &lt;br /&gt;
 public:&lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag,&lt;br /&gt;
             const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual ~example1_device_config();&lt;br /&gt;
 &lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, &lt;br /&gt;
             const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
 &lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
 &lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
 &lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
 &lt;br /&gt;
 protected:&lt;br /&gt;
     // internal state&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you see the DISABLE_COPYING macro; this just defines a standard copy constructor and copy operator as private so that you can&#039;t accidentally assign a device and implicitly make a copy (which would be bad)&lt;br /&gt;
&lt;br /&gt;
* You&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
(more later)&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3196</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3196"/>
		<updated>2010-05-21T20:05:45Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* A Basic Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Example #1: Simple Device with Static Configuration=&lt;br /&gt;
&lt;br /&gt;
For this example, we will define a new device that uses a static configuration. Drivers using this device will need to declare a static const instance of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct below and specify a pointer to that struct as part of the machine configuration.&lt;br /&gt;
&lt;br /&gt;
Starting with the header file, we first define what the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct looks like:&lt;br /&gt;
&lt;br /&gt;
 struct example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     int           m_device_integer_data;&lt;br /&gt;
     const char *  m_device_string_data;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This structure can contain pretty much anything. However, it is very important that the struct be a &amp;quot;plain old data&amp;quot; (or POD) type. This means that there should be no constructor and no virtual methods. The reason for this is that there are thousands of drivers defined in the system, and if each of them defined a static const structure like this that needed to execute its constructor on startup, it would adversely impact the overall startup time of the emulator. So just don&#039;t do it.&lt;br /&gt;
&lt;br /&gt;
Next, we define the device configuration class:&lt;br /&gt;
&lt;br /&gt;
 class example1_device_config : public device_config, &lt;br /&gt;
                                public example1_device_config_data&lt;br /&gt;
 {&lt;br /&gt;
     DISABLE_COPYING(example1_device_config );&lt;br /&gt;
&lt;br /&gt;
     friend class example1_device;&lt;br /&gt;
&lt;br /&gt;
 public:&lt;br /&gt;
     // construction/destruction&lt;br /&gt;
     example1_device_config(const machine_config &amp;amp;mconfig, device_type type, const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual ~example1_device_config();&lt;br /&gt;
&lt;br /&gt;
     // allocators&lt;br /&gt;
     static device_config *static_alloc_device_config(const machine_config &amp;amp;mconfig, const char *tag, const device_config *owner, UINT32 clock);&lt;br /&gt;
     virtual device_t *alloc_device(running_machine &amp;amp;machine, const device_config &amp;amp;config) const;&lt;br /&gt;
&lt;br /&gt;
     // basic information getters&lt;br /&gt;
     virtual const char *name() const { return &amp;quot;Example Device 1&amp;quot;; }&lt;br /&gt;
&lt;br /&gt;
     // device-level overrides&lt;br /&gt;
     virtual void device_config_complete();&lt;br /&gt;
     virtual bool device_validity_check(const game_driver &amp;amp;driver) const;&lt;br /&gt;
&lt;br /&gt;
     // add accessors for any device-specific config that might be needed publically&lt;br /&gt;
&lt;br /&gt;
 protected:&lt;br /&gt;
     // internal state&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Ok, there is a lot of good and subtle information here. Let&#039;s walk through the declaration step by step:&lt;br /&gt;
&lt;br /&gt;
* First thing to note is that the class is defined as inheriting from both &#039;&#039;&#039;device_config&#039;&#039;&#039; and &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; (our static configuration structure). While it is not strictly necessary, it is convenient to do so because the members of the &#039;&#039;&#039;example1_device_config_data&#039;&#039;&#039; struct effectively become members of the device configuration class, making them easier to access without extra indirection. Making this work also implies copying the user provided data up into your configuration class, which is done later in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
* Next you see the DISABLE_COPYING macro; this just defines a standard copy constructor and copy operator as private so that you can&#039;t accidentally assign a device and implicitly make a copy (which would be bad)&lt;br /&gt;
&lt;br /&gt;
* You&#039;ll see we added &#039;&#039;&#039;example1_device&#039;&#039;&#039; as a friend class. In general, it is recommended to keep your configuration state private/protected, but allow the associated device to have free access to it by friending it. If external code needs to query your configuration directly, just add simple accessors to the configuration state (the need for this should be rare).&lt;br /&gt;
&lt;br /&gt;
(more later)&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3195</id>
		<title>MAME Coding Conventions</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3195"/>
		<updated>2010-05-21T19:45:01Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Language conventions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is WIP. Please don&#039;t edit it until this notice is removed.&lt;br /&gt;
&lt;br /&gt;
MAME is a project that has had many contributors from many different backgrounds. Throughout its history, there have never really been any kind of formal coding conventions defined, although thanks to imitation, there is at least a glimmer of consistency.&lt;br /&gt;
&lt;br /&gt;
In general, a codebase with consistent conventions is easier to understand than one with varying conventions. However, trying to impose a strict order on a project of this magnitude is certainly taking things too far.&lt;br /&gt;
&lt;br /&gt;
If you categorize the MAME codebase, you can look at it like this:&lt;br /&gt;
* OS-specific code (OSD)&lt;br /&gt;
* MAME &amp;quot;core&amp;quot; code&lt;br /&gt;
* CPU cores&lt;br /&gt;
* Sound engines&lt;br /&gt;
* Game drivers&lt;br /&gt;
&lt;br /&gt;
The first two pieces (the core and OSD) are in general only handled by a small group of developers, while the remaining pieces (drivers and CPU/sound cores) come from a much broader audience. Furthermore, the drivers and CPU/sound cores all interact to some degree with core and OSD pieces below them, so the most benefit from code clarity and consistency comes from making the core and OSD pieces consistent.&lt;br /&gt;
&lt;br /&gt;
With that in mind, below is an outline some of the key coding conventions currently in use in the core and OSD layers. If you are modifying code in these layers and wish to have it accepted upon submission, you would do well to keep to these guidelines. (In fact, if you are modifying any file in any project, you should adopt the conventions of that file/project, rather than just stuffing your own inconsistent style in the middle of something else. I can&#039;t believe how many people just ignore the existing styles and jam their own style in the middle.)&lt;br /&gt;
&lt;br /&gt;
One more thing. Keep in mind that coding conventions are like religion: they are often strongly-held beliefs with little factual justification to back them up. You may disagree with them. Heck, even I disagree with a few of them. But they are the conventions that are used. Deal with it.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
* function, method, and variable names are named using the &amp;lt;code&amp;gt;lower_under_convention&amp;lt;/code&amp;gt;&lt;br /&gt;
* static member functions should have a static_ prefix (e.g., &amp;lt;code&amp;gt;static_timer_callback&amp;lt;/code&amp;gt;)&lt;br /&gt;
* member variables within a class should have a standard prefix, as follows:&lt;br /&gt;
** normal variables should have an m_ prefix (e.g., &amp;lt;code&amp;gt;m_device&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;m_config&amp;lt;/code&amp;gt;, etc)&lt;br /&gt;
** static members should have an s_ prefix (e.g., &amp;lt;code&amp;gt;s_device_table&amp;lt;/code&amp;gt;)&lt;br /&gt;
** static constant members should have a k_ prefix (e.g., &amp;lt;code&amp;gt;k_maximum_items&amp;lt;/code&amp;gt;)&lt;br /&gt;
* macros, enum items, and #defined constants should be named using the &amp;lt;code&amp;gt;ALL_CAPS_UNDER_CONVENTION&amp;lt;/code&amp;gt;&lt;br /&gt;
* constants which are part of a group should have a common prefix; example: &amp;lt;code&amp;gt;enum { ADDRESS_SPACE_PROGRAM, ADDRESS_SPACE_DATA, ADDRESS_SPACE_IO };&amp;lt;/code&amp;gt;&lt;br /&gt;
* prefer descriptive variable names (&amp;lt;code&amp;gt;sampnum&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memoffset&amp;lt;/code&amp;gt;) over single-letter names (&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;j&amp;lt;/code&amp;gt;)&lt;br /&gt;
* never use the prefix &amp;quot;my&amp;quot; for anything; it&#039;s not &amp;quot;myobject&amp;quot;, just use &amp;quot;object&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
* comments in the code are preferred to be &amp;lt;code&amp;gt;// C++-style comments&amp;lt;/code&amp;gt;, though &amp;lt;code&amp;gt;/* standard C-style comments */&amp;lt;/code&amp;gt; are still very common&lt;br /&gt;
* each function should have a comment preceding it that briefly describes what that function does&lt;br /&gt;
* each file should begin with a header that includes information about the licensing of that file; if no licensing information is given, the standard MAME license is assumed&lt;br /&gt;
&lt;br /&gt;
== Spacing ==&lt;br /&gt;
* a space should be used between binary and trinary operators &amp;amp;mdash; example: &amp;lt;code&amp;gt;a + b / 2&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used around parentheses in expressions &amp;amp;mdash; example: &amp;lt;code&amp;gt;(((i + j) * k) &amp;gt;&amp;gt; m)&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used between a function and its parameters &amp;amp;mdash; example: &amp;lt;code&amp;gt;function(param1, param2)&amp;lt;/code&amp;gt;&lt;br /&gt;
* a space should be used between keywords (if, while, for) and their arguments &amp;amp;mdash; example: &amp;lt;code&amp;gt;for (x = 0; x &amp;lt; 10; x++)&amp;lt;/code&amp;gt;&lt;br /&gt;
* opening/closing braces should be on their own line, and should be indented to align with the start of the statement that introduces them&lt;br /&gt;
* two blank lines should separate the end of a function from the start of the next function&lt;br /&gt;
&lt;br /&gt;
== Expressions ==&lt;br /&gt;
* do not use parentheses with &#039;&#039;&#039;return&#039;&#039;&#039;, it is not a function &amp;amp;mdash; example: &amp;lt;code&amp;gt;return 0;&amp;lt;/code&amp;gt;&lt;br /&gt;
* do not overuse parentheses except to clarify a statement &amp;amp;mdash; example: &amp;lt;code&amp;gt;if (a &amp;gt;= 10 &amp;amp;&amp;amp; a &amp;lt; 20)&amp;lt;/code&amp;gt;&lt;br /&gt;
* always use NULL (not 0) when working with pointers&lt;br /&gt;
* make comparisons against NULL explicit: &amp;lt;code&amp;gt;if (ptr != NULL)&amp;lt;/code&amp;gt;&lt;br /&gt;
* make comparisons against 0 explicit: &amp;lt;code&amp;gt;if (strcmp(string1, string2) == 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;don&#039;t&#039;&#039; make comparisons against boolean values explicit: &amp;lt;code&amp;gt;val = (a == b); if (val)...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Language conventions ==&lt;br /&gt;
* prefer references over pointers, using pointers primarily in situations where NULL is a valid option&lt;br /&gt;
* use &#039;&#039;&#039;static&#039;&#039;&#039; and &#039;&#039;&#039;const&#039;&#039;&#039; keywords aggressively where appropriate&lt;br /&gt;
* create typedefs for function pointers; example: &amp;lt;code&amp;gt;typedef void (*my_callback_func)(UINT32 param);&amp;lt;/code&amp;gt;&lt;br /&gt;
* make calls through function pointers explicit &amp;amp;mdash; example: &amp;lt;code&amp;gt;(*funcptr)(a, b)&amp;lt;/code&amp;gt;&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;enum&#039;&#039;&#039; instead of a macro&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;inline&#039;&#039;&#039; functions instead of macros&lt;br /&gt;
* wherever possible, use templates instead of macros&lt;br /&gt;
* macros that look like functions should be wrapped with &amp;lt;code&amp;gt;do { &amp;amp;lt;macrobody&amp;amp;gt; } while (0)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
* avoid declaring static variables inside a function scope &amp;amp;mdash; these are really global variables and belong at the top of the module&lt;br /&gt;
* declare all global variables at the top of the file&lt;br /&gt;
* use the MAME-defined types: &amp;lt;code&amp;gt;INT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT64&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Header Files ==&lt;br /&gt;
* the preferred order of definitions in a header file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** reinclusion protection (see below)&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables&lt;br /&gt;
** function prototypes&lt;br /&gt;
** and inline functions&lt;br /&gt;
* function prototypes in header files generally do not use an &#039;&#039;&#039;extern&#039;&#039;&#039; qualifier&lt;br /&gt;
* all header files should support reinclusion; this is done by adding the following to the top of each header&lt;br /&gt;
 #pragma once&lt;br /&gt;
 &lt;br /&gt;
 #ifndef __FILENAME_H__&lt;br /&gt;
 #define __FILENAME_H__&lt;br /&gt;
and adding&lt;br /&gt;
 #endif /* __FILENAME__H__ */&lt;br /&gt;
to the end. Note that &amp;lt;code&amp;gt;#pragma once&amp;lt;/code&amp;gt; is provided because it is generally faster when supported. Since not all compilers do support it, the &amp;lt;code&amp;gt;#ifndef/#define&amp;lt;/code&amp;gt; methods are retained as a fallback.&lt;br /&gt;
&lt;br /&gt;
== Source Files ==&lt;br /&gt;
* the preferred order of code in a source file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables (both static and global)&lt;br /&gt;
** internal function prototypes&lt;br /&gt;
** inline functions&lt;br /&gt;
** externally referenced functions&lt;br /&gt;
** internal functions (in same order as prototyped)&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3194</id>
		<title>MAME Coding Conventions</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3194"/>
		<updated>2010-05-21T19:41:25Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is WIP. Please don&#039;t edit it until this notice is removed.&lt;br /&gt;
&lt;br /&gt;
MAME is a project that has had many contributors from many different backgrounds. Throughout its history, there have never really been any kind of formal coding conventions defined, although thanks to imitation, there is at least a glimmer of consistency.&lt;br /&gt;
&lt;br /&gt;
In general, a codebase with consistent conventions is easier to understand than one with varying conventions. However, trying to impose a strict order on a project of this magnitude is certainly taking things too far.&lt;br /&gt;
&lt;br /&gt;
If you categorize the MAME codebase, you can look at it like this:&lt;br /&gt;
* OS-specific code (OSD)&lt;br /&gt;
* MAME &amp;quot;core&amp;quot; code&lt;br /&gt;
* CPU cores&lt;br /&gt;
* Sound engines&lt;br /&gt;
* Game drivers&lt;br /&gt;
&lt;br /&gt;
The first two pieces (the core and OSD) are in general only handled by a small group of developers, while the remaining pieces (drivers and CPU/sound cores) come from a much broader audience. Furthermore, the drivers and CPU/sound cores all interact to some degree with core and OSD pieces below them, so the most benefit from code clarity and consistency comes from making the core and OSD pieces consistent.&lt;br /&gt;
&lt;br /&gt;
With that in mind, below is an outline some of the key coding conventions currently in use in the core and OSD layers. If you are modifying code in these layers and wish to have it accepted upon submission, you would do well to keep to these guidelines. (In fact, if you are modifying any file in any project, you should adopt the conventions of that file/project, rather than just stuffing your own inconsistent style in the middle of something else. I can&#039;t believe how many people just ignore the existing styles and jam their own style in the middle.)&lt;br /&gt;
&lt;br /&gt;
One more thing. Keep in mind that coding conventions are like religion: they are often strongly-held beliefs with little factual justification to back them up. You may disagree with them. Heck, even I disagree with a few of them. But they are the conventions that are used. Deal with it.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
* function, method, and variable names are named using the &amp;lt;code&amp;gt;lower_under_convention&amp;lt;/code&amp;gt;&lt;br /&gt;
* static member functions should have a static_ prefix (e.g., &amp;lt;code&amp;gt;static_timer_callback&amp;lt;/code&amp;gt;)&lt;br /&gt;
* member variables within a class should have a standard prefix, as follows:&lt;br /&gt;
** normal variables should have an m_ prefix (e.g., &amp;lt;code&amp;gt;m_device&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;m_config&amp;lt;/code&amp;gt;, etc)&lt;br /&gt;
** static members should have an s_ prefix (e.g., &amp;lt;code&amp;gt;s_device_table&amp;lt;/code&amp;gt;)&lt;br /&gt;
** static constant members should have a k_ prefix (e.g., &amp;lt;code&amp;gt;k_maximum_items&amp;lt;/code&amp;gt;)&lt;br /&gt;
* macros, enum items, and #defined constants should be named using the &amp;lt;code&amp;gt;ALL_CAPS_UNDER_CONVENTION&amp;lt;/code&amp;gt;&lt;br /&gt;
* constants which are part of a group should have a common prefix; example: &amp;lt;code&amp;gt;enum { ADDRESS_SPACE_PROGRAM, ADDRESS_SPACE_DATA, ADDRESS_SPACE_IO };&amp;lt;/code&amp;gt;&lt;br /&gt;
* prefer descriptive variable names (&amp;lt;code&amp;gt;sampnum&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memoffset&amp;lt;/code&amp;gt;) over single-letter names (&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;j&amp;lt;/code&amp;gt;)&lt;br /&gt;
* never use the prefix &amp;quot;my&amp;quot; for anything; it&#039;s not &amp;quot;myobject&amp;quot;, just use &amp;quot;object&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
* comments in the code are preferred to be &amp;lt;code&amp;gt;// C++-style comments&amp;lt;/code&amp;gt;, though &amp;lt;code&amp;gt;/* standard C-style comments */&amp;lt;/code&amp;gt; are still very common&lt;br /&gt;
* each function should have a comment preceding it that briefly describes what that function does&lt;br /&gt;
* each file should begin with a header that includes information about the licensing of that file; if no licensing information is given, the standard MAME license is assumed&lt;br /&gt;
&lt;br /&gt;
== Spacing ==&lt;br /&gt;
* a space should be used between binary and trinary operators &amp;amp;mdash; example: &amp;lt;code&amp;gt;a + b / 2&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used around parentheses in expressions &amp;amp;mdash; example: &amp;lt;code&amp;gt;(((i + j) * k) &amp;gt;&amp;gt; m)&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used between a function and its parameters &amp;amp;mdash; example: &amp;lt;code&amp;gt;function(param1, param2)&amp;lt;/code&amp;gt;&lt;br /&gt;
* a space should be used between keywords (if, while, for) and their arguments &amp;amp;mdash; example: &amp;lt;code&amp;gt;for (x = 0; x &amp;lt; 10; x++)&amp;lt;/code&amp;gt;&lt;br /&gt;
* opening/closing braces should be on their own line, and should be indented to align with the start of the statement that introduces them&lt;br /&gt;
* two blank lines should separate the end of a function from the start of the next function&lt;br /&gt;
&lt;br /&gt;
== Expressions ==&lt;br /&gt;
* do not use parentheses with &#039;&#039;&#039;return&#039;&#039;&#039;, it is not a function &amp;amp;mdash; example: &amp;lt;code&amp;gt;return 0;&amp;lt;/code&amp;gt;&lt;br /&gt;
* do not overuse parentheses except to clarify a statement &amp;amp;mdash; example: &amp;lt;code&amp;gt;if (a &amp;gt;= 10 &amp;amp;&amp;amp; a &amp;lt; 20)&amp;lt;/code&amp;gt;&lt;br /&gt;
* always use NULL (not 0) when working with pointers&lt;br /&gt;
* make comparisons against NULL explicit: &amp;lt;code&amp;gt;if (ptr != NULL)&amp;lt;/code&amp;gt;&lt;br /&gt;
* make comparisons against 0 explicit: &amp;lt;code&amp;gt;if (strcmp(string1, string2) == 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;don&#039;t&#039;&#039; make comparisons against boolean values explicit: &amp;lt;code&amp;gt;val = (a == b); if (val)...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Language conventions ==&lt;br /&gt;
* use &#039;&#039;&#039;static&#039;&#039;&#039; and &#039;&#039;&#039;const&#039;&#039;&#039; keywords aggressively where appropriate&lt;br /&gt;
* create typedefs for function pointers; example: &amp;lt;code&amp;gt;typedef void (*my_callback_func)(UINT32 param);&amp;lt;/code&amp;gt;&lt;br /&gt;
* make calls through function pointers explicit &amp;amp;mdash; example: &amp;lt;code&amp;gt;(*funcptr)(a, b)&amp;lt;/code&amp;gt;&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;enum&#039;&#039;&#039; instead of a macro&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;inline&#039;&#039;&#039; functions instead of macros&lt;br /&gt;
* wherever possible, use templates instead of macros&lt;br /&gt;
* macros that look like functions should be wrapped with &amp;lt;code&amp;gt;do { &amp;amp;lt;macrobody&amp;amp;gt; } while (0)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
* avoid declaring static variables inside a function scope &amp;amp;mdash; these are really global variables and belong at the top of the module&lt;br /&gt;
* declare all global variables at the top of the file&lt;br /&gt;
* use the MAME-defined types: &amp;lt;code&amp;gt;INT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT64&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Header Files ==&lt;br /&gt;
* the preferred order of definitions in a header file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** reinclusion protection (see below)&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables&lt;br /&gt;
** function prototypes&lt;br /&gt;
** and inline functions&lt;br /&gt;
* function prototypes in header files generally do not use an &#039;&#039;&#039;extern&#039;&#039;&#039; qualifier&lt;br /&gt;
* all header files should support reinclusion; this is done by adding the following to the top of each header&lt;br /&gt;
 #pragma once&lt;br /&gt;
 &lt;br /&gt;
 #ifndef __FILENAME_H__&lt;br /&gt;
 #define __FILENAME_H__&lt;br /&gt;
and adding&lt;br /&gt;
 #endif /* __FILENAME__H__ */&lt;br /&gt;
to the end. Note that &amp;lt;code&amp;gt;#pragma once&amp;lt;/code&amp;gt; is provided because it is generally faster when supported. Since not all compilers do support it, the &amp;lt;code&amp;gt;#ifndef/#define&amp;lt;/code&amp;gt; methods are retained as a fallback.&lt;br /&gt;
&lt;br /&gt;
== Source Files ==&lt;br /&gt;
* the preferred order of code in a source file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables (both static and global)&lt;br /&gt;
** internal function prototypes&lt;br /&gt;
** inline functions&lt;br /&gt;
** externally referenced functions&lt;br /&gt;
** internal functions (in same order as prototyped)&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3193</id>
		<title>MAME Coding Conventions</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3193"/>
		<updated>2010-05-21T19:40:37Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Language conventions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is WIP. Please don&#039;t edit it until this notice is removed.&lt;br /&gt;
&lt;br /&gt;
MAME is a project that has had many contributors from many different backgrounds. Throughout its history, there have never really been any kind of formal coding conventions defined, although thanks to imitation, there is at least a glimmer of consistency.&lt;br /&gt;
&lt;br /&gt;
In general, a codebase with consistent conventions is easier to understand than one with varying conventions. However, trying to impose a strict order on a project of this magnitude is certainly taking things too far.&lt;br /&gt;
&lt;br /&gt;
If you categorize the MAME codebase, you can look at it like this:&lt;br /&gt;
* OS-specific code (OSD)&lt;br /&gt;
* MAME &amp;quot;core&amp;quot; code&lt;br /&gt;
* CPU cores&lt;br /&gt;
* Sound engines&lt;br /&gt;
* Game drivers&lt;br /&gt;
&lt;br /&gt;
The first two pieces (the core and OSD) are in general only handled by a small group of developers, while the remaining pieces (drivers and CPU/sound cores) come from a much broader audience. Furthermore, the drivers and CPU/sound cores all interact to some degree with core and OSD pieces below them, so the most benefit from code clarity and consistency comes from making the core and OSD pieces consistent.&lt;br /&gt;
&lt;br /&gt;
With that in mind, below is an outline some of the key coding conventions currently in use in the core and OSD layers. If you are modifying code in theses layers and wish to have it accepted upon submission, you would do well to keep to these guidelines. (In fact, if you are modifying any file in any project, you should adopt the conventions of that file/project, rather than just stuffing your own inconsistent style in the middle of something else. I can&#039;t believe how many people just ignore the existing styles and jam their own style in the middle.)&lt;br /&gt;
&lt;br /&gt;
One more thing. Keep in mind that coding conventions are like religion: they are often strongly-held beliefs with little factual justification to back them up. You may disagree with them. Heck, even I disagree with a few of them. But they are the conventions that are used. Deal with it.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
* function, method, and variable names are named using the &amp;lt;code&amp;gt;lower_under_convention&amp;lt;/code&amp;gt;&lt;br /&gt;
* static member functions should have a static_ prefix (e.g., &amp;lt;code&amp;gt;static_timer_callback&amp;lt;/code&amp;gt;)&lt;br /&gt;
* member variables within a class should have a standard prefix, as follows:&lt;br /&gt;
** normal variables should have an m_ prefix (e.g., &amp;lt;code&amp;gt;m_device&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;m_config&amp;lt;/code&amp;gt;, etc)&lt;br /&gt;
** static members should have an s_ prefix (e.g., &amp;lt;code&amp;gt;s_device_table&amp;lt;/code&amp;gt;)&lt;br /&gt;
** static constant members should have a k_ prefix (e.g., &amp;lt;code&amp;gt;k_maximum_items&amp;lt;/code&amp;gt;)&lt;br /&gt;
* macros, enum items, and #defined constants should be named using the &amp;lt;code&amp;gt;ALL_CAPS_UNDER_CONVENTION&amp;lt;/code&amp;gt;&lt;br /&gt;
* constants which are part of a group should have a common prefix; example: &amp;lt;code&amp;gt;enum { ADDRESS_SPACE_PROGRAM, ADDRESS_SPACE_DATA, ADDRESS_SPACE_IO };&amp;lt;/code&amp;gt;&lt;br /&gt;
* prefer descriptive variable names (&amp;lt;code&amp;gt;sampnum&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memoffset&amp;lt;/code&amp;gt;) over single-letter names (&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;j&amp;lt;/code&amp;gt;)&lt;br /&gt;
* never use the prefix &amp;quot;my&amp;quot; for anything; it&#039;s not &amp;quot;myobject&amp;quot;, just use &amp;quot;object&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
* comments in the code are preferred to be &amp;lt;code&amp;gt;// C++-style comments&amp;lt;/code&amp;gt;, though &amp;lt;code&amp;gt;/* standard C-style comments */&amp;lt;/code&amp;gt; are still very common&lt;br /&gt;
* each function should have a comment preceding it that briefly describes what that function does&lt;br /&gt;
* each file should begin with a header that includes information about the licensing of that file; if no licensing information is given, the standard MAME license is assumed&lt;br /&gt;
&lt;br /&gt;
== Spacing ==&lt;br /&gt;
* a space should be used between binary and trinary operators &amp;amp;mdash; example: &amp;lt;code&amp;gt;a + b / 2&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used around parentheses in expressions &amp;amp;mdash; example: &amp;lt;code&amp;gt;(((i + j) * k) &amp;gt;&amp;gt; m)&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used between a function and its parameters &amp;amp;mdash; example: &amp;lt;code&amp;gt;function(param1, param2)&amp;lt;/code&amp;gt;&lt;br /&gt;
* a space should be used between keywords (if, while, for) and their arguments &amp;amp;mdash; example: &amp;lt;code&amp;gt;for (x = 0; x &amp;lt; 10; x++)&amp;lt;/code&amp;gt;&lt;br /&gt;
* opening/closing braces should be on their own line, and should be indented to align with the start of the statement that introduces them&lt;br /&gt;
* two blank lines should separate the end of a function from the start of the next function&lt;br /&gt;
&lt;br /&gt;
== Expressions ==&lt;br /&gt;
* do not use parentheses with &#039;&#039;&#039;return&#039;&#039;&#039;, it is not a function &amp;amp;mdash; example: &amp;lt;code&amp;gt;return 0;&amp;lt;/code&amp;gt;&lt;br /&gt;
* do not overuse parentheses except to clarify a statement &amp;amp;mdash; example: &amp;lt;code&amp;gt;if (a &amp;gt;= 10 &amp;amp;&amp;amp; a &amp;lt; 20)&amp;lt;/code&amp;gt;&lt;br /&gt;
* always use NULL (not 0) when working with pointers&lt;br /&gt;
* make comparisons against NULL explicit: &amp;lt;code&amp;gt;if (ptr != NULL)&amp;lt;/code&amp;gt;&lt;br /&gt;
* make comparisons against 0 explicit: &amp;lt;code&amp;gt;if (strcmp(string1, string2) == 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;don&#039;t&#039;&#039; make comparisons against boolean values explicit: &amp;lt;code&amp;gt;val = (a == b); if (val)...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Language conventions ==&lt;br /&gt;
* use &#039;&#039;&#039;static&#039;&#039;&#039; and &#039;&#039;&#039;const&#039;&#039;&#039; keywords aggressively where appropriate&lt;br /&gt;
* create typedefs for function pointers; example: &amp;lt;code&amp;gt;typedef void (*my_callback_func)(UINT32 param);&amp;lt;/code&amp;gt;&lt;br /&gt;
* make calls through function pointers explicit &amp;amp;mdash; example: &amp;lt;code&amp;gt;(*funcptr)(a, b)&amp;lt;/code&amp;gt;&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;enum&#039;&#039;&#039; instead of a macro&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;inline&#039;&#039;&#039; functions instead of macros&lt;br /&gt;
* wherever possible, use templates instead of macros&lt;br /&gt;
* macros that look like functions should be wrapped with &amp;lt;code&amp;gt;do { &amp;amp;lt;macrobody&amp;amp;gt; } while (0)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
* avoid declaring static variables inside a function scope &amp;amp;mdash; these are really global variables and belong at the top of the module&lt;br /&gt;
* declare all global variables at the top of the file&lt;br /&gt;
* use the MAME-defined types: &amp;lt;code&amp;gt;INT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT64&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Header Files ==&lt;br /&gt;
* the preferred order of definitions in a header file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** reinclusion protection (see below)&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables&lt;br /&gt;
** function prototypes&lt;br /&gt;
** and inline functions&lt;br /&gt;
* function prototypes in header files generally do not use an &#039;&#039;&#039;extern&#039;&#039;&#039; qualifier&lt;br /&gt;
* all header files should support reinclusion; this is done by adding the following to the top of each header&lt;br /&gt;
 #pragma once&lt;br /&gt;
 &lt;br /&gt;
 #ifndef __FILENAME_H__&lt;br /&gt;
 #define __FILENAME_H__&lt;br /&gt;
and adding&lt;br /&gt;
 #endif /* __FILENAME__H__ */&lt;br /&gt;
to the end. Note that &amp;lt;code&amp;gt;#pragma once&amp;lt;/code&amp;gt; is provided because it is generally faster when supported. Since not all compilers do support it, the &amp;lt;code&amp;gt;#ifndef/#define&amp;lt;/code&amp;gt; methods are retained as a fallback.&lt;br /&gt;
&lt;br /&gt;
== Source Files ==&lt;br /&gt;
* the preferred order of code in a source file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables (both static and global)&lt;br /&gt;
** internal function prototypes&lt;br /&gt;
** inline functions&lt;br /&gt;
** externally referenced functions&lt;br /&gt;
** internal functions (in same order as prototyped)&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3192</id>
		<title>MAME Coding Conventions</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3192"/>
		<updated>2010-05-21T19:39:22Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Comments */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is WIP. Please don&#039;t edit it until this notice is removed.&lt;br /&gt;
&lt;br /&gt;
MAME is a project that has had many contributors from many different backgrounds. Throughout its history, there have never really been any kind of formal coding conventions defined, although thanks to imitation, there is at least a glimmer of consistency.&lt;br /&gt;
&lt;br /&gt;
In general, a codebase with consistent conventions is easier to understand than one with varying conventions. However, trying to impose a strict order on a project of this magnitude is certainly taking things too far.&lt;br /&gt;
&lt;br /&gt;
If you categorize the MAME codebase, you can look at it like this:&lt;br /&gt;
* OS-specific code (OSD)&lt;br /&gt;
* MAME &amp;quot;core&amp;quot; code&lt;br /&gt;
* CPU cores&lt;br /&gt;
* Sound engines&lt;br /&gt;
* Game drivers&lt;br /&gt;
&lt;br /&gt;
The first two pieces (the core and OSD) are in general only handled by a small group of developers, while the remaining pieces (drivers and CPU/sound cores) come from a much broader audience. Furthermore, the drivers and CPU/sound cores all interact to some degree with core and OSD pieces below them, so the most benefit from code clarity and consistency comes from making the core and OSD pieces consistent.&lt;br /&gt;
&lt;br /&gt;
With that in mind, below is an outline some of the key coding conventions currently in use in the core and OSD layers. If you are modifying code in theses layers and wish to have it accepted upon submission, you would do well to keep to these guidelines. (In fact, if you are modifying any file in any project, you should adopt the conventions of that file/project, rather than just stuffing your own inconsistent style in the middle of something else. I can&#039;t believe how many people just ignore the existing styles and jam their own style in the middle.)&lt;br /&gt;
&lt;br /&gt;
One more thing. Keep in mind that coding conventions are like religion: they are often strongly-held beliefs with little factual justification to back them up. You may disagree with them. Heck, even I disagree with a few of them. But they are the conventions that are used. Deal with it.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
* function, method, and variable names are named using the &amp;lt;code&amp;gt;lower_under_convention&amp;lt;/code&amp;gt;&lt;br /&gt;
* static member functions should have a static_ prefix (e.g., &amp;lt;code&amp;gt;static_timer_callback&amp;lt;/code&amp;gt;)&lt;br /&gt;
* member variables within a class should have a standard prefix, as follows:&lt;br /&gt;
** normal variables should have an m_ prefix (e.g., &amp;lt;code&amp;gt;m_device&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;m_config&amp;lt;/code&amp;gt;, etc)&lt;br /&gt;
** static members should have an s_ prefix (e.g., &amp;lt;code&amp;gt;s_device_table&amp;lt;/code&amp;gt;)&lt;br /&gt;
** static constant members should have a k_ prefix (e.g., &amp;lt;code&amp;gt;k_maximum_items&amp;lt;/code&amp;gt;)&lt;br /&gt;
* macros, enum items, and #defined constants should be named using the &amp;lt;code&amp;gt;ALL_CAPS_UNDER_CONVENTION&amp;lt;/code&amp;gt;&lt;br /&gt;
* constants which are part of a group should have a common prefix; example: &amp;lt;code&amp;gt;enum { ADDRESS_SPACE_PROGRAM, ADDRESS_SPACE_DATA, ADDRESS_SPACE_IO };&amp;lt;/code&amp;gt;&lt;br /&gt;
* prefer descriptive variable names (&amp;lt;code&amp;gt;sampnum&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memoffset&amp;lt;/code&amp;gt;) over single-letter names (&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;j&amp;lt;/code&amp;gt;)&lt;br /&gt;
* never use the prefix &amp;quot;my&amp;quot; for anything; it&#039;s not &amp;quot;myobject&amp;quot;, just use &amp;quot;object&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
* comments in the code are preferred to be &amp;lt;code&amp;gt;// C++-style comments&amp;lt;/code&amp;gt;, though &amp;lt;code&amp;gt;/* standard C-style comments */&amp;lt;/code&amp;gt; are still very common&lt;br /&gt;
* each function should have a comment preceding it that briefly describes what that function does&lt;br /&gt;
* each file should begin with a header that includes information about the licensing of that file; if no licensing information is given, the standard MAME license is assumed&lt;br /&gt;
&lt;br /&gt;
== Spacing ==&lt;br /&gt;
* a space should be used between binary and trinary operators &amp;amp;mdash; example: &amp;lt;code&amp;gt;a + b / 2&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used around parentheses in expressions &amp;amp;mdash; example: &amp;lt;code&amp;gt;(((i + j) * k) &amp;gt;&amp;gt; m)&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used between a function and its parameters &amp;amp;mdash; example: &amp;lt;code&amp;gt;function(param1, param2)&amp;lt;/code&amp;gt;&lt;br /&gt;
* a space should be used between keywords (if, while, for) and their arguments &amp;amp;mdash; example: &amp;lt;code&amp;gt;for (x = 0; x &amp;lt; 10; x++)&amp;lt;/code&amp;gt;&lt;br /&gt;
* opening/closing braces should be on their own line, and should be indented to align with the start of the statement that introduces them&lt;br /&gt;
* two blank lines should separate the end of a function from the start of the next function&lt;br /&gt;
&lt;br /&gt;
== Expressions ==&lt;br /&gt;
* do not use parentheses with &#039;&#039;&#039;return&#039;&#039;&#039;, it is not a function &amp;amp;mdash; example: &amp;lt;code&amp;gt;return 0;&amp;lt;/code&amp;gt;&lt;br /&gt;
* do not overuse parentheses except to clarify a statement &amp;amp;mdash; example: &amp;lt;code&amp;gt;if (a &amp;gt;= 10 &amp;amp;&amp;amp; a &amp;lt; 20)&amp;lt;/code&amp;gt;&lt;br /&gt;
* always use NULL (not 0) when working with pointers&lt;br /&gt;
* make comparisons against NULL explicit: &amp;lt;code&amp;gt;if (ptr != NULL)&amp;lt;/code&amp;gt;&lt;br /&gt;
* make comparisons against 0 explicit: &amp;lt;code&amp;gt;if (strcmp(string1, string2) == 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;don&#039;t&#039;&#039; make comparisons against boolean values explicit: &amp;lt;code&amp;gt;val = (a == b); if (val)...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Language conventions ==&lt;br /&gt;
* use &#039;&#039;&#039;static&#039;&#039;&#039; and &#039;&#039;&#039;const&#039;&#039;&#039; keywords aggressively where appropriate&lt;br /&gt;
* create typedefs for function pointers; example: &amp;lt;code&amp;gt;typedef void (*my_callback_func)(UINT32 param);&amp;lt;/code&amp;gt;&lt;br /&gt;
* make calls through function pointers explicit &amp;amp;mdash; example: &amp;lt;code&amp;gt;(*funcptr)(a, b)&amp;lt;/code&amp;gt;&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;enum&#039;&#039;&#039; instead of a macro&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;INLINE&#039;&#039;&#039; functions instead of macros&lt;br /&gt;
* macros that look like functions should be wrapped with &amp;lt;code&amp;gt;do { &amp;amp;lt;macrobody&amp;amp;gt; } while (0)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
* avoid declaring static variables inside a function scope &amp;amp;mdash; these are really global variables and belong at the top of the module&lt;br /&gt;
* declare all global variables at the top of the file&lt;br /&gt;
* use the MAME-defined types: &amp;lt;code&amp;gt;INT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT64&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Header Files ==&lt;br /&gt;
* the preferred order of definitions in a header file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** reinclusion protection (see below)&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables&lt;br /&gt;
** function prototypes&lt;br /&gt;
** and inline functions&lt;br /&gt;
* function prototypes in header files generally do not use an &#039;&#039;&#039;extern&#039;&#039;&#039; qualifier&lt;br /&gt;
* all header files should support reinclusion; this is done by adding the following to the top of each header&lt;br /&gt;
 #pragma once&lt;br /&gt;
 &lt;br /&gt;
 #ifndef __FILENAME_H__&lt;br /&gt;
 #define __FILENAME_H__&lt;br /&gt;
and adding&lt;br /&gt;
 #endif /* __FILENAME__H__ */&lt;br /&gt;
to the end. Note that &amp;lt;code&amp;gt;#pragma once&amp;lt;/code&amp;gt; is provided because it is generally faster when supported. Since not all compilers do support it, the &amp;lt;code&amp;gt;#ifndef/#define&amp;lt;/code&amp;gt; methods are retained as a fallback.&lt;br /&gt;
&lt;br /&gt;
== Source Files ==&lt;br /&gt;
* the preferred order of code in a source file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables (both static and global)&lt;br /&gt;
** internal function prototypes&lt;br /&gt;
** inline functions&lt;br /&gt;
** externally referenced functions&lt;br /&gt;
** internal functions (in same order as prototyped)&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3191</id>
		<title>MAME Coding Conventions</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3191"/>
		<updated>2010-05-21T19:37:50Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Naming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is WIP. Please don&#039;t edit it until this notice is removed.&lt;br /&gt;
&lt;br /&gt;
MAME is a project that has had many contributors from many different backgrounds. Throughout its history, there have never really been any kind of formal coding conventions defined, although thanks to imitation, there is at least a glimmer of consistency.&lt;br /&gt;
&lt;br /&gt;
In general, a codebase with consistent conventions is easier to understand than one with varying conventions. However, trying to impose a strict order on a project of this magnitude is certainly taking things too far.&lt;br /&gt;
&lt;br /&gt;
If you categorize the MAME codebase, you can look at it like this:&lt;br /&gt;
* OS-specific code (OSD)&lt;br /&gt;
* MAME &amp;quot;core&amp;quot; code&lt;br /&gt;
* CPU cores&lt;br /&gt;
* Sound engines&lt;br /&gt;
* Game drivers&lt;br /&gt;
&lt;br /&gt;
The first two pieces (the core and OSD) are in general only handled by a small group of developers, while the remaining pieces (drivers and CPU/sound cores) come from a much broader audience. Furthermore, the drivers and CPU/sound cores all interact to some degree with core and OSD pieces below them, so the most benefit from code clarity and consistency comes from making the core and OSD pieces consistent.&lt;br /&gt;
&lt;br /&gt;
With that in mind, below is an outline some of the key coding conventions currently in use in the core and OSD layers. If you are modifying code in theses layers and wish to have it accepted upon submission, you would do well to keep to these guidelines. (In fact, if you are modifying any file in any project, you should adopt the conventions of that file/project, rather than just stuffing your own inconsistent style in the middle of something else. I can&#039;t believe how many people just ignore the existing styles and jam their own style in the middle.)&lt;br /&gt;
&lt;br /&gt;
One more thing. Keep in mind that coding conventions are like religion: they are often strongly-held beliefs with little factual justification to back them up. You may disagree with them. Heck, even I disagree with a few of them. But they are the conventions that are used. Deal with it.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
* function, method, and variable names are named using the &amp;lt;code&amp;gt;lower_under_convention&amp;lt;/code&amp;gt;&lt;br /&gt;
* static member functions should have a static_ prefix (e.g., &amp;lt;code&amp;gt;static_timer_callback&amp;lt;/code&amp;gt;)&lt;br /&gt;
* member variables within a class should have a standard prefix, as follows:&lt;br /&gt;
** normal variables should have an m_ prefix (e.g., &amp;lt;code&amp;gt;m_device&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;m_config&amp;lt;/code&amp;gt;, etc)&lt;br /&gt;
** static members should have an s_ prefix (e.g., &amp;lt;code&amp;gt;s_device_table&amp;lt;/code&amp;gt;)&lt;br /&gt;
** static constant members should have a k_ prefix (e.g., &amp;lt;code&amp;gt;k_maximum_items&amp;lt;/code&amp;gt;)&lt;br /&gt;
* macros, enum items, and #defined constants should be named using the &amp;lt;code&amp;gt;ALL_CAPS_UNDER_CONVENTION&amp;lt;/code&amp;gt;&lt;br /&gt;
* constants which are part of a group should have a common prefix; example: &amp;lt;code&amp;gt;enum { ADDRESS_SPACE_PROGRAM, ADDRESS_SPACE_DATA, ADDRESS_SPACE_IO };&amp;lt;/code&amp;gt;&lt;br /&gt;
* prefer descriptive variable names (&amp;lt;code&amp;gt;sampnum&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memoffset&amp;lt;/code&amp;gt;) over single-letter names (&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;j&amp;lt;/code&amp;gt;)&lt;br /&gt;
* never use the prefix &amp;quot;my&amp;quot; for anything; it&#039;s not &amp;quot;myobject&amp;quot;, just use &amp;quot;object&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
* comments in the non-OSD parts of the code should all be &amp;lt;code&amp;gt;/* C-style comments */&amp;lt;/code&amp;gt;&lt;br /&gt;
* comments in the OSD-specific parts of the code may be &amp;lt;code&amp;gt;// C++-style comments&amp;lt;/code&amp;gt; (and are in the Windows code)&lt;br /&gt;
* each function should have a comment preceding it that briefly describes what that function does&lt;br /&gt;
&lt;br /&gt;
== Spacing ==&lt;br /&gt;
* a space should be used between binary and trinary operators &amp;amp;mdash; example: &amp;lt;code&amp;gt;a + b / 2&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used around parentheses in expressions &amp;amp;mdash; example: &amp;lt;code&amp;gt;(((i + j) * k) &amp;gt;&amp;gt; m)&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used between a function and its parameters &amp;amp;mdash; example: &amp;lt;code&amp;gt;function(param1, param2)&amp;lt;/code&amp;gt;&lt;br /&gt;
* a space should be used between keywords (if, while, for) and their arguments &amp;amp;mdash; example: &amp;lt;code&amp;gt;for (x = 0; x &amp;lt; 10; x++)&amp;lt;/code&amp;gt;&lt;br /&gt;
* opening/closing braces should be on their own line, and should be indented to align with the start of the statement that introduces them&lt;br /&gt;
* two blank lines should separate the end of a function from the start of the next function&lt;br /&gt;
&lt;br /&gt;
== Expressions ==&lt;br /&gt;
* do not use parentheses with &#039;&#039;&#039;return&#039;&#039;&#039;, it is not a function &amp;amp;mdash; example: &amp;lt;code&amp;gt;return 0;&amp;lt;/code&amp;gt;&lt;br /&gt;
* do not overuse parentheses except to clarify a statement &amp;amp;mdash; example: &amp;lt;code&amp;gt;if (a &amp;gt;= 10 &amp;amp;&amp;amp; a &amp;lt; 20)&amp;lt;/code&amp;gt;&lt;br /&gt;
* always use NULL (not 0) when working with pointers&lt;br /&gt;
* make comparisons against NULL explicit: &amp;lt;code&amp;gt;if (ptr != NULL)&amp;lt;/code&amp;gt;&lt;br /&gt;
* make comparisons against 0 explicit: &amp;lt;code&amp;gt;if (strcmp(string1, string2) == 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;don&#039;t&#039;&#039; make comparisons against boolean values explicit: &amp;lt;code&amp;gt;val = (a == b); if (val)...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Language conventions ==&lt;br /&gt;
* use &#039;&#039;&#039;static&#039;&#039;&#039; and &#039;&#039;&#039;const&#039;&#039;&#039; keywords aggressively where appropriate&lt;br /&gt;
* create typedefs for function pointers; example: &amp;lt;code&amp;gt;typedef void (*my_callback_func)(UINT32 param);&amp;lt;/code&amp;gt;&lt;br /&gt;
* make calls through function pointers explicit &amp;amp;mdash; example: &amp;lt;code&amp;gt;(*funcptr)(a, b)&amp;lt;/code&amp;gt;&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;enum&#039;&#039;&#039; instead of a macro&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;INLINE&#039;&#039;&#039; functions instead of macros&lt;br /&gt;
* macros that look like functions should be wrapped with &amp;lt;code&amp;gt;do { &amp;amp;lt;macrobody&amp;amp;gt; } while (0)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
* avoid declaring static variables inside a function scope &amp;amp;mdash; these are really global variables and belong at the top of the module&lt;br /&gt;
* declare all global variables at the top of the file&lt;br /&gt;
* use the MAME-defined types: &amp;lt;code&amp;gt;INT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT64&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Header Files ==&lt;br /&gt;
* the preferred order of definitions in a header file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** reinclusion protection (see below)&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables&lt;br /&gt;
** function prototypes&lt;br /&gt;
** and inline functions&lt;br /&gt;
* function prototypes in header files generally do not use an &#039;&#039;&#039;extern&#039;&#039;&#039; qualifier&lt;br /&gt;
* all header files should support reinclusion; this is done by adding the following to the top of each header&lt;br /&gt;
 #pragma once&lt;br /&gt;
 &lt;br /&gt;
 #ifndef __FILENAME_H__&lt;br /&gt;
 #define __FILENAME_H__&lt;br /&gt;
and adding&lt;br /&gt;
 #endif /* __FILENAME__H__ */&lt;br /&gt;
to the end. Note that &amp;lt;code&amp;gt;#pragma once&amp;lt;/code&amp;gt; is provided because it is generally faster when supported. Since not all compilers do support it, the &amp;lt;code&amp;gt;#ifndef/#define&amp;lt;/code&amp;gt; methods are retained as a fallback.&lt;br /&gt;
&lt;br /&gt;
== Source Files ==&lt;br /&gt;
* the preferred order of code in a source file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables (both static and global)&lt;br /&gt;
** internal function prototypes&lt;br /&gt;
** inline functions&lt;br /&gt;
** externally referenced functions&lt;br /&gt;
** internal functions (in same order as prototyped)&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3190</id>
		<title>MAME Coding Conventions</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3190"/>
		<updated>2010-05-21T19:37:09Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Naming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is WIP. Please don&#039;t edit it until this notice is removed.&lt;br /&gt;
&lt;br /&gt;
MAME is a project that has had many contributors from many different backgrounds. Throughout its history, there have never really been any kind of formal coding conventions defined, although thanks to imitation, there is at least a glimmer of consistency.&lt;br /&gt;
&lt;br /&gt;
In general, a codebase with consistent conventions is easier to understand than one with varying conventions. However, trying to impose a strict order on a project of this magnitude is certainly taking things too far.&lt;br /&gt;
&lt;br /&gt;
If you categorize the MAME codebase, you can look at it like this:&lt;br /&gt;
* OS-specific code (OSD)&lt;br /&gt;
* MAME &amp;quot;core&amp;quot; code&lt;br /&gt;
* CPU cores&lt;br /&gt;
* Sound engines&lt;br /&gt;
* Game drivers&lt;br /&gt;
&lt;br /&gt;
The first two pieces (the core and OSD) are in general only handled by a small group of developers, while the remaining pieces (drivers and CPU/sound cores) come from a much broader audience. Furthermore, the drivers and CPU/sound cores all interact to some degree with core and OSD pieces below them, so the most benefit from code clarity and consistency comes from making the core and OSD pieces consistent.&lt;br /&gt;
&lt;br /&gt;
With that in mind, below is an outline some of the key coding conventions currently in use in the core and OSD layers. If you are modifying code in theses layers and wish to have it accepted upon submission, you would do well to keep to these guidelines. (In fact, if you are modifying any file in any project, you should adopt the conventions of that file/project, rather than just stuffing your own inconsistent style in the middle of something else. I can&#039;t believe how many people just ignore the existing styles and jam their own style in the middle.)&lt;br /&gt;
&lt;br /&gt;
One more thing. Keep in mind that coding conventions are like religion: they are often strongly-held beliefs with little factual justification to back them up. You may disagree with them. Heck, even I disagree with a few of them. But they are the conventions that are used. Deal with it.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
* function, method, and variable names are named using the &amp;lt;code&amp;gt;lower_under_convention&amp;lt;/code&amp;gt;&lt;br /&gt;
* static member functions should have a static_ prefix (e.g., static_timer_callback)&lt;br /&gt;
* member variables within a class should have a standard prefix, as follows:&lt;br /&gt;
** normal variables should have an m_ prefix (e.g., m_device, m_config, etc)&lt;br /&gt;
** static members should have an s_ prefix (e.g., s_device_table)&lt;br /&gt;
** static constant members should have a k_ prefix (e.g., k_maximum_items)&lt;br /&gt;
* macros, enum items, and #defined constants should be named using the &amp;lt;code&amp;gt;ALL_CAPS_UNDER_CONVENTION&amp;lt;/code&amp;gt;&lt;br /&gt;
* constants which are part of a group should have a common prefix; example: &amp;lt;code&amp;gt;enum { ADDRESS_SPACE_PROGRAM, ADDRESS_SPACE_DATA, ADDRESS_SPACE_IO };&amp;lt;/code&amp;gt;&lt;br /&gt;
* prefer descriptive variable names (&amp;lt;code&amp;gt;sampnum&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memoffset&amp;lt;/code&amp;gt;) over single-letter names (&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;j&amp;lt;/code&amp;gt;)&lt;br /&gt;
* never use the prefix &amp;quot;my&amp;quot; for anything; it&#039;s not &amp;quot;myobject&amp;quot;, just use &amp;quot;object&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
* comments in the non-OSD parts of the code should all be &amp;lt;code&amp;gt;/* C-style comments */&amp;lt;/code&amp;gt;&lt;br /&gt;
* comments in the OSD-specific parts of the code may be &amp;lt;code&amp;gt;// C++-style comments&amp;lt;/code&amp;gt; (and are in the Windows code)&lt;br /&gt;
* each function should have a comment preceding it that briefly describes what that function does&lt;br /&gt;
&lt;br /&gt;
== Spacing ==&lt;br /&gt;
* a space should be used between binary and trinary operators &amp;amp;mdash; example: &amp;lt;code&amp;gt;a + b / 2&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used around parentheses in expressions &amp;amp;mdash; example: &amp;lt;code&amp;gt;(((i + j) * k) &amp;gt;&amp;gt; m)&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used between a function and its parameters &amp;amp;mdash; example: &amp;lt;code&amp;gt;function(param1, param2)&amp;lt;/code&amp;gt;&lt;br /&gt;
* a space should be used between keywords (if, while, for) and their arguments &amp;amp;mdash; example: &amp;lt;code&amp;gt;for (x = 0; x &amp;lt; 10; x++)&amp;lt;/code&amp;gt;&lt;br /&gt;
* opening/closing braces should be on their own line, and should be indented to align with the start of the statement that introduces them&lt;br /&gt;
* two blank lines should separate the end of a function from the start of the next function&lt;br /&gt;
&lt;br /&gt;
== Expressions ==&lt;br /&gt;
* do not use parentheses with &#039;&#039;&#039;return&#039;&#039;&#039;, it is not a function &amp;amp;mdash; example: &amp;lt;code&amp;gt;return 0;&amp;lt;/code&amp;gt;&lt;br /&gt;
* do not overuse parentheses except to clarify a statement &amp;amp;mdash; example: &amp;lt;code&amp;gt;if (a &amp;gt;= 10 &amp;amp;&amp;amp; a &amp;lt; 20)&amp;lt;/code&amp;gt;&lt;br /&gt;
* always use NULL (not 0) when working with pointers&lt;br /&gt;
* make comparisons against NULL explicit: &amp;lt;code&amp;gt;if (ptr != NULL)&amp;lt;/code&amp;gt;&lt;br /&gt;
* make comparisons against 0 explicit: &amp;lt;code&amp;gt;if (strcmp(string1, string2) == 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;don&#039;t&#039;&#039; make comparisons against boolean values explicit: &amp;lt;code&amp;gt;val = (a == b); if (val)...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Language conventions ==&lt;br /&gt;
* use &#039;&#039;&#039;static&#039;&#039;&#039; and &#039;&#039;&#039;const&#039;&#039;&#039; keywords aggressively where appropriate&lt;br /&gt;
* create typedefs for function pointers; example: &amp;lt;code&amp;gt;typedef void (*my_callback_func)(UINT32 param);&amp;lt;/code&amp;gt;&lt;br /&gt;
* make calls through function pointers explicit &amp;amp;mdash; example: &amp;lt;code&amp;gt;(*funcptr)(a, b)&amp;lt;/code&amp;gt;&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;enum&#039;&#039;&#039; instead of a macro&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;INLINE&#039;&#039;&#039; functions instead of macros&lt;br /&gt;
* macros that look like functions should be wrapped with &amp;lt;code&amp;gt;do { &amp;amp;lt;macrobody&amp;amp;gt; } while (0)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
* avoid declaring static variables inside a function scope &amp;amp;mdash; these are really global variables and belong at the top of the module&lt;br /&gt;
* declare all global variables at the top of the file&lt;br /&gt;
* use the MAME-defined types: &amp;lt;code&amp;gt;INT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT64&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Header Files ==&lt;br /&gt;
* the preferred order of definitions in a header file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** reinclusion protection (see below)&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables&lt;br /&gt;
** function prototypes&lt;br /&gt;
** and inline functions&lt;br /&gt;
* function prototypes in header files generally do not use an &#039;&#039;&#039;extern&#039;&#039;&#039; qualifier&lt;br /&gt;
* all header files should support reinclusion; this is done by adding the following to the top of each header&lt;br /&gt;
 #pragma once&lt;br /&gt;
 &lt;br /&gt;
 #ifndef __FILENAME_H__&lt;br /&gt;
 #define __FILENAME_H__&lt;br /&gt;
and adding&lt;br /&gt;
 #endif /* __FILENAME__H__ */&lt;br /&gt;
to the end. Note that &amp;lt;code&amp;gt;#pragma once&amp;lt;/code&amp;gt; is provided because it is generally faster when supported. Since not all compilers do support it, the &amp;lt;code&amp;gt;#ifndef/#define&amp;lt;/code&amp;gt; methods are retained as a fallback.&lt;br /&gt;
&lt;br /&gt;
== Source Files ==&lt;br /&gt;
* the preferred order of code in a source file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables (both static and global)&lt;br /&gt;
** internal function prototypes&lt;br /&gt;
** inline functions&lt;br /&gt;
** externally referenced functions&lt;br /&gt;
** internal functions (in same order as prototyped)&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3189</id>
		<title>MAME Coding Conventions</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Coding_Conventions&amp;diff=3189"/>
		<updated>2010-05-21T19:36:24Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Naming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is WIP. Please don&#039;t edit it until this notice is removed.&lt;br /&gt;
&lt;br /&gt;
MAME is a project that has had many contributors from many different backgrounds. Throughout its history, there have never really been any kind of formal coding conventions defined, although thanks to imitation, there is at least a glimmer of consistency.&lt;br /&gt;
&lt;br /&gt;
In general, a codebase with consistent conventions is easier to understand than one with varying conventions. However, trying to impose a strict order on a project of this magnitude is certainly taking things too far.&lt;br /&gt;
&lt;br /&gt;
If you categorize the MAME codebase, you can look at it like this:&lt;br /&gt;
* OS-specific code (OSD)&lt;br /&gt;
* MAME &amp;quot;core&amp;quot; code&lt;br /&gt;
* CPU cores&lt;br /&gt;
* Sound engines&lt;br /&gt;
* Game drivers&lt;br /&gt;
&lt;br /&gt;
The first two pieces (the core and OSD) are in general only handled by a small group of developers, while the remaining pieces (drivers and CPU/sound cores) come from a much broader audience. Furthermore, the drivers and CPU/sound cores all interact to some degree with core and OSD pieces below them, so the most benefit from code clarity and consistency comes from making the core and OSD pieces consistent.&lt;br /&gt;
&lt;br /&gt;
With that in mind, below is an outline some of the key coding conventions currently in use in the core and OSD layers. If you are modifying code in theses layers and wish to have it accepted upon submission, you would do well to keep to these guidelines. (In fact, if you are modifying any file in any project, you should adopt the conventions of that file/project, rather than just stuffing your own inconsistent style in the middle of something else. I can&#039;t believe how many people just ignore the existing styles and jam their own style in the middle.)&lt;br /&gt;
&lt;br /&gt;
One more thing. Keep in mind that coding conventions are like religion: they are often strongly-held beliefs with little factual justification to back them up. You may disagree with them. Heck, even I disagree with a few of them. But they are the conventions that are used. Deal with it.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
* function, method, and variable names are named using the &amp;lt;code&amp;gt;lower_under_convention&amp;lt;/code&amp;gt;&lt;br /&gt;
* member variables within a class should have a standard prefix, as follows:&lt;br /&gt;
** normal variables should have an m_ prefix (e.g., m_device, m_config, etc)&lt;br /&gt;
** static members should have an s_ prefix (e.g., s_device_table)&lt;br /&gt;
** static constant members should have a k_ prefix (e.g., k_maximum_items)&lt;br /&gt;
* macros, enum items, and #defined constants should be named using the &amp;lt;code&amp;gt;ALL_CAPS_UNDER_CONVENTION&amp;lt;/code&amp;gt;&lt;br /&gt;
* constants which are part of a group should have a common prefix; example: &amp;lt;code&amp;gt;enum { ADDRESS_SPACE_PROGRAM, ADDRESS_SPACE_DATA, ADDRESS_SPACE_IO };&amp;lt;/code&amp;gt;&lt;br /&gt;
* prefer descriptive variable names (&amp;lt;code&amp;gt;sampnum&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memoffset&amp;lt;/code&amp;gt;) over single-letter names (&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;j&amp;lt;/code&amp;gt;)&lt;br /&gt;
* never use the prefix &amp;quot;my&amp;quot; for anything; it&#039;s not &amp;quot;myobject&amp;quot;, just use &amp;quot;object&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
* comments in the non-OSD parts of the code should all be &amp;lt;code&amp;gt;/* C-style comments */&amp;lt;/code&amp;gt;&lt;br /&gt;
* comments in the OSD-specific parts of the code may be &amp;lt;code&amp;gt;// C++-style comments&amp;lt;/code&amp;gt; (and are in the Windows code)&lt;br /&gt;
* each function should have a comment preceding it that briefly describes what that function does&lt;br /&gt;
&lt;br /&gt;
== Spacing ==&lt;br /&gt;
* a space should be used between binary and trinary operators &amp;amp;mdash; example: &amp;lt;code&amp;gt;a + b / 2&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used around parentheses in expressions &amp;amp;mdash; example: &amp;lt;code&amp;gt;(((i + j) * k) &amp;gt;&amp;gt; m)&amp;lt;/code&amp;gt;&lt;br /&gt;
* spaces should &#039;&#039;&#039;not&#039;&#039;&#039; be used between a function and its parameters &amp;amp;mdash; example: &amp;lt;code&amp;gt;function(param1, param2)&amp;lt;/code&amp;gt;&lt;br /&gt;
* a space should be used between keywords (if, while, for) and their arguments &amp;amp;mdash; example: &amp;lt;code&amp;gt;for (x = 0; x &amp;lt; 10; x++)&amp;lt;/code&amp;gt;&lt;br /&gt;
* opening/closing braces should be on their own line, and should be indented to align with the start of the statement that introduces them&lt;br /&gt;
* two blank lines should separate the end of a function from the start of the next function&lt;br /&gt;
&lt;br /&gt;
== Expressions ==&lt;br /&gt;
* do not use parentheses with &#039;&#039;&#039;return&#039;&#039;&#039;, it is not a function &amp;amp;mdash; example: &amp;lt;code&amp;gt;return 0;&amp;lt;/code&amp;gt;&lt;br /&gt;
* do not overuse parentheses except to clarify a statement &amp;amp;mdash; example: &amp;lt;code&amp;gt;if (a &amp;gt;= 10 &amp;amp;&amp;amp; a &amp;lt; 20)&amp;lt;/code&amp;gt;&lt;br /&gt;
* always use NULL (not 0) when working with pointers&lt;br /&gt;
* make comparisons against NULL explicit: &amp;lt;code&amp;gt;if (ptr != NULL)&amp;lt;/code&amp;gt;&lt;br /&gt;
* make comparisons against 0 explicit: &amp;lt;code&amp;gt;if (strcmp(string1, string2) == 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;don&#039;t&#039;&#039; make comparisons against boolean values explicit: &amp;lt;code&amp;gt;val = (a == b); if (val)...&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Language conventions ==&lt;br /&gt;
* use &#039;&#039;&#039;static&#039;&#039;&#039; and &#039;&#039;&#039;const&#039;&#039;&#039; keywords aggressively where appropriate&lt;br /&gt;
* create typedefs for function pointers; example: &amp;lt;code&amp;gt;typedef void (*my_callback_func)(UINT32 param);&amp;lt;/code&amp;gt;&lt;br /&gt;
* make calls through function pointers explicit &amp;amp;mdash; example: &amp;lt;code&amp;gt;(*funcptr)(a, b)&amp;lt;/code&amp;gt;&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;enum&#039;&#039;&#039; instead of a macro&lt;br /&gt;
* wherever possible, use &#039;&#039;&#039;INLINE&#039;&#039;&#039; functions instead of macros&lt;br /&gt;
* macros that look like functions should be wrapped with &amp;lt;code&amp;gt;do { &amp;amp;lt;macrobody&amp;amp;gt; } while (0)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
* avoid declaring static variables inside a function scope &amp;amp;mdash; these are really global variables and belong at the top of the module&lt;br /&gt;
* declare all global variables at the top of the file&lt;br /&gt;
* use the MAME-defined types: &amp;lt;code&amp;gt;INT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT16&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT32&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INT64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UINT64&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Header Files ==&lt;br /&gt;
* the preferred order of definitions in a header file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** reinclusion protection (see below)&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables&lt;br /&gt;
** function prototypes&lt;br /&gt;
** and inline functions&lt;br /&gt;
* function prototypes in header files generally do not use an &#039;&#039;&#039;extern&#039;&#039;&#039; qualifier&lt;br /&gt;
* all header files should support reinclusion; this is done by adding the following to the top of each header&lt;br /&gt;
 #pragma once&lt;br /&gt;
 &lt;br /&gt;
 #ifndef __FILENAME_H__&lt;br /&gt;
 #define __FILENAME_H__&lt;br /&gt;
and adding&lt;br /&gt;
 #endif /* __FILENAME__H__ */&lt;br /&gt;
to the end. Note that &amp;lt;code&amp;gt;#pragma once&amp;lt;/code&amp;gt; is provided because it is generally faster when supported. Since not all compilers do support it, the &amp;lt;code&amp;gt;#ifndef/#define&amp;lt;/code&amp;gt; methods are retained as a fallback.&lt;br /&gt;
&lt;br /&gt;
== Source Files ==&lt;br /&gt;
* the preferred order of code in a source file is:&lt;br /&gt;
** standard header&lt;br /&gt;
** includes&lt;br /&gt;
** debugging flags&lt;br /&gt;
** constants&lt;br /&gt;
** type definitions&lt;br /&gt;
** macros&lt;br /&gt;
** global variables (both static and global)&lt;br /&gt;
** internal function prototypes&lt;br /&gt;
** inline functions&lt;br /&gt;
** externally referenced functions&lt;br /&gt;
** internal functions (in same order as prototyped)&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3188</id>
		<title>Device Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=Device_Interfaces&amp;diff=3188"/>
		<updated>2010-05-21T19:31:40Z</updated>

		<summary type="html">&lt;p&gt;Aaron: New page: =Standard Interfaces=  * Execute * Memory * State * NVRAM * Disassembly * Sound  =Custom Interface=&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
* Execute&lt;br /&gt;
* Memory&lt;br /&gt;
* State&lt;br /&gt;
* NVRAM&lt;br /&gt;
* Disassembly&lt;br /&gt;
* Sound&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3187</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3187"/>
		<updated>2010-05-21T19:31:27Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=A Basic Example=&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=How_MAME_Works&amp;diff=3186</id>
		<title>How MAME Works</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=How_MAME_Works&amp;diff=3186"/>
		<updated>2010-05-21T19:31:07Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Core Internals */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following is a list of documents describing the internal workings (core) of the MAME emulator.  Most are penned by Aaron Giles.&lt;br /&gt;
&lt;br /&gt;
== Building MAME ==&lt;br /&gt;
* [[Building MAME using Microsoft Visual Studio compilers]]&lt;br /&gt;
&lt;br /&gt;
== Writing for MAME ==&lt;br /&gt;
* [[Contributing to MAME]]&lt;br /&gt;
* [[Submitting Source Code]]&lt;br /&gt;
* [[MAME Coding Conventions]]&lt;br /&gt;
&lt;br /&gt;
== For Driver Writers ==&lt;br /&gt;
* [[Game Drivers]]&lt;br /&gt;
* [[Resource Management in MAME]]&lt;br /&gt;
* [[DIP Switches in MAME]]&lt;br /&gt;
* [[MAME Interrupt Function Review]]&lt;br /&gt;
* [[Using MAME&#039;s tilemap system]]&lt;br /&gt;
* [[Programmable Logic Devices in MAME]]&lt;br /&gt;
* [[CPUs and Address Spaces]]&lt;br /&gt;
* [[Address Maps]]&lt;br /&gt;
&lt;br /&gt;
== Core Internals ==&lt;br /&gt;
* MAME Devices&lt;br /&gt;
** [[MAME Device Basics]]&lt;br /&gt;
** [[Device Interfaces]]&lt;br /&gt;
** [[Advanced Device Customization]]&lt;br /&gt;
** [[All About Devices]] (out of date)&lt;br /&gt;
* [[Timers and timing]]&lt;br /&gt;
* [[Filters and streams in the MAME Sound System]]&lt;br /&gt;
* [[Save State Fundamentals]]&lt;br /&gt;
* [[Using the GFX/TileMap viewer (F4)]]&lt;br /&gt;
* [[How To Use the &#039;New&#039; Renderer]]&lt;br /&gt;
* [[Layouts and Rendering for MAME Artwork System]]&lt;br /&gt;
* [[LAY File Basics - Part I]]&lt;br /&gt;
&lt;br /&gt;
== CPU Emulation ==&lt;br /&gt;
* [[Virtual TLB]]&lt;br /&gt;
* [[CPU Scheduling in MAME]]&lt;br /&gt;
&lt;br /&gt;
== Universal Dynamic Recompiler ==&lt;br /&gt;
* [[Core Concepts]]&lt;br /&gt;
* [[UML Architecture]]&lt;br /&gt;
** [[UML Control Flow Opcodes]]&lt;br /&gt;
** [[UML Internal Register Opcodes]]&lt;br /&gt;
** [[UML Integer Opcodes]]&lt;br /&gt;
** [[UML Floating Point Opcodes]]&lt;br /&gt;
* [[Dynamic Recompiler Author&#039;s Guide]]&lt;br /&gt;
* [[Back-End Author&#039;s Guide]]&lt;br /&gt;
&lt;br /&gt;
== Tips &amp;amp; Tricks ==&lt;br /&gt;
* [[Executing Code Out of a Memory Region With a Read Handler]]&lt;br /&gt;
* [[Checklist for Cleaning Up Drivers]]&lt;br /&gt;
* [[Writing Messages to the Screen In a MAME Driver]]&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3185</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3185"/>
		<updated>2010-05-21T19:30:02Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Lifecycle of a Device */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
This section aims to describe the two core device classes and how they are used by the system.&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
* Execute&lt;br /&gt;
* Memory&lt;br /&gt;
* State&lt;br /&gt;
* NVRAM&lt;br /&gt;
* Disassembly&lt;br /&gt;
* Sound&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;br /&gt;
&lt;br /&gt;
=A Basic Example=&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3184</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3184"/>
		<updated>2010-05-21T19:29:25Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Basic Concepts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Core Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
* Execute&lt;br /&gt;
* Memory&lt;br /&gt;
* State&lt;br /&gt;
* NVRAM&lt;br /&gt;
* Disassembly&lt;br /&gt;
* Sound&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;br /&gt;
&lt;br /&gt;
=A Basic Example=&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=How_MAME_Works&amp;diff=3183</id>
		<title>How MAME Works</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=How_MAME_Works&amp;diff=3183"/>
		<updated>2010-05-21T19:29:02Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Core Internals */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following is a list of documents describing the internal workings (core) of the MAME emulator.  Most are penned by Aaron Giles.&lt;br /&gt;
&lt;br /&gt;
== Building MAME ==&lt;br /&gt;
* [[Building MAME using Microsoft Visual Studio compilers]]&lt;br /&gt;
&lt;br /&gt;
== Writing for MAME ==&lt;br /&gt;
* [[Contributing to MAME]]&lt;br /&gt;
* [[Submitting Source Code]]&lt;br /&gt;
* [[MAME Coding Conventions]]&lt;br /&gt;
&lt;br /&gt;
== For Driver Writers ==&lt;br /&gt;
* [[Game Drivers]]&lt;br /&gt;
* [[Resource Management in MAME]]&lt;br /&gt;
* [[DIP Switches in MAME]]&lt;br /&gt;
* [[MAME Interrupt Function Review]]&lt;br /&gt;
* [[Using MAME&#039;s tilemap system]]&lt;br /&gt;
* [[Programmable Logic Devices in MAME]]&lt;br /&gt;
* [[CPUs and Address Spaces]]&lt;br /&gt;
* [[Address Maps]]&lt;br /&gt;
&lt;br /&gt;
== Core Internals ==&lt;br /&gt;
* [[MAME Device Basics]]&lt;br /&gt;
** [[All About Devices]] (out of date)&lt;br /&gt;
* [[Timers and timing]]&lt;br /&gt;
* [[Filters and streams in the MAME Sound System]]&lt;br /&gt;
* [[Save State Fundamentals]]&lt;br /&gt;
* [[Using the GFX/TileMap viewer (F4)]]&lt;br /&gt;
* [[How To Use the &#039;New&#039; Renderer]]&lt;br /&gt;
* [[Layouts and Rendering for MAME Artwork System]]&lt;br /&gt;
* [[LAY File Basics - Part I]]&lt;br /&gt;
&lt;br /&gt;
== CPU Emulation ==&lt;br /&gt;
* [[Virtual TLB]]&lt;br /&gt;
* [[CPU Scheduling in MAME]]&lt;br /&gt;
&lt;br /&gt;
== Universal Dynamic Recompiler ==&lt;br /&gt;
* [[Core Concepts]]&lt;br /&gt;
* [[UML Architecture]]&lt;br /&gt;
** [[UML Control Flow Opcodes]]&lt;br /&gt;
** [[UML Internal Register Opcodes]]&lt;br /&gt;
** [[UML Integer Opcodes]]&lt;br /&gt;
** [[UML Floating Point Opcodes]]&lt;br /&gt;
* [[Dynamic Recompiler Author&#039;s Guide]]&lt;br /&gt;
* [[Back-End Author&#039;s Guide]]&lt;br /&gt;
&lt;br /&gt;
== Tips &amp;amp; Tricks ==&lt;br /&gt;
* [[Executing Code Out of a Memory Region With a Read Handler]]&lt;br /&gt;
* [[Checklist for Cleaning Up Drivers]]&lt;br /&gt;
* [[Writing Messages to the Screen In a MAME Driver]]&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3181</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3181"/>
		<updated>2010-05-21T19:28:39Z</updated>

		<summary type="html">&lt;p&gt;Aaron: MAME Devices moved to MAME Device Basics: Will need several articles&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
* Execute&lt;br /&gt;
* Memory&lt;br /&gt;
* State&lt;br /&gt;
* NVRAM&lt;br /&gt;
* Disassembly&lt;br /&gt;
* Sound&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;br /&gt;
&lt;br /&gt;
=A Basic Example=&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3180</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3180"/>
		<updated>2010-05-20T22:55:32Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Configuring Devices */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
Inline configurations, by contrast, don&#039;t require an external structure. Instead, all the information needed to configure the device is specified inline via the machine configuration macros. The way this works is that the base &#039;&#039;&#039;device_config&#039;&#039;&#039; class has a small array &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] of 64-bit values, which can be populated via the MCONFIG_TOKEN_DEVICE_INLINE_DATA* tokens. Each token specifies an index in the array, along with a 16-bit, 32-bit, or 64-bit data value to be stored there.&lt;br /&gt;
&lt;br /&gt;
The raw macros used to emit the tokens that specify inline data look like this:&lt;br /&gt;
&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA16(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA32(index, data)&lt;br /&gt;
 MDRV_DEVICE_INLINE_DATA64(index, data)&lt;br /&gt;
&lt;br /&gt;
Note that the size (16, 32, 64) reflects the number of bits needed to hold the maximum data value. Regardless of the size specified here, the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array is always an array of 64-bit values. Care should be used if a signed value is truncated to 16 bits via the MDRV_DEVICE_INLINE_DATA16() macro. When extracting the result from the &#039;&#039;&#039;m_inline_data&#039;&#039;&#039;[] array, it needs to be explicitly sign-extended.&lt;br /&gt;
&lt;br /&gt;
The indexes that map which data is stored in which entry in the inline data array should be defined as a public enumeration within the device-specific configuration class. This keeps the global namespace less polluted and ensures no overlapping of indices.&lt;br /&gt;
&lt;br /&gt;
In all cases, it is recommended that devices using inline data define nicer, more descriptive macros for specifying that data, rather than encouraging the user to operate with raw data and indexes. These custom macros can allow for more compact specification of the data, and can even be combined with the device&#039;s custom MDRV_DEVICE_ADD() macro to further simplify things for the user. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
 #define MDRV_SPEAKER_ADD(_tag, _x, _y, _z) \&lt;br /&gt;
     MDRV_DEVICE_ADD(_tag, SPEAKER, 0) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_X, (_x) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Y, (_y) * (double)(1 &amp;lt;&amp;lt; 24)) \&lt;br /&gt;
     MDRV_DEVICE_INLINE_DATA32(speaker_device_config::INLINE_Z, (_z) * (double)(1 &amp;lt;&amp;lt; 24))&lt;br /&gt;
&lt;br /&gt;
In this case, a single line in the machine configuration:&lt;br /&gt;
&lt;br /&gt;
 MDRV_SPEAKER_ADD(&amp;quot;center&amp;quot;, 0.0, 0.0, 1.0)&lt;br /&gt;
&lt;br /&gt;
not only adds the device but also specifies all of its required parameters inline. (Note that because the parameters are floating-point values, they are converted to 8.24 fixed point first, since only integral values can be stored in the inline data array.)&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
* Execute&lt;br /&gt;
* Memory&lt;br /&gt;
* State&lt;br /&gt;
* NVRAM&lt;br /&gt;
* Disassembly&lt;br /&gt;
* Sound&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;br /&gt;
&lt;br /&gt;
=A Basic Example=&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3179</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3179"/>
		<updated>2010-05-19T20:16:24Z</updated>

		<summary type="html">&lt;p&gt;Aaron: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
Device configuration comes in two flavors, static configuration and inline configuration. The decision as to which to use is fairly arbitrary -- and in fact both can be used at the same time! The example from the Lifecycle of a Device chapter demonstrates the use of both types of configuration:&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)    // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) // inline configuration&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)            // static configuration&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0) // AND inline configuration&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by examining how static configuration work, as they are the simplest to understand. A static configuration is simply a single pointer to a constant structure, defined by the game driver, and expressed via the token stream as an MCONFIG_TOKEN_DEVICE_CONFIG token, followed by a pointer to the structure.&lt;br /&gt;
&lt;br /&gt;
Within a machine driver configuration, a static configuration is specified by a MDRV_DEVICE_CONFIG() macro. Certain devices and device types might also provide aliases to this, like the MDRV_SOUND_CONFIG() macro above. If you look at the pacman.c driver, you&#039;ll see the configuration structure:&lt;br /&gt;
&lt;br /&gt;
 static const namco_interface namco_config =&lt;br /&gt;
 {&lt;br /&gt;
     3,			/* number of voices */&lt;br /&gt;
     0			/* stereo */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
When a driver specifies a static configuration, the pointer is extracted from the token stream and deposited into the void pointer &#039;&#039;&#039;m_static_config&#039;&#039;&#039;, stored by the &#039;&#039;&#039;device_config&#039;&#039;&#039; base class. The driver-specific configuration class can then consume this pointer when its &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method is called, or it can leave it around for the device itself to consume when it is later instantiated (see the Best Practices section for recommendations on how to cleanly consume the static configuration).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Standard Interfaces=&lt;br /&gt;
&lt;br /&gt;
* Execute&lt;br /&gt;
* Memory&lt;br /&gt;
* State&lt;br /&gt;
* NVRAM&lt;br /&gt;
* Disassembly&lt;br /&gt;
* Sound&lt;br /&gt;
&lt;br /&gt;
=Custom Interface=&lt;br /&gt;
&lt;br /&gt;
=A Basic Example=&lt;br /&gt;
&lt;br /&gt;
=Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3178</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3178"/>
		<updated>2010-05-19T20:03:00Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Runtime */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
In addition to these basic interfaces, there are several other key times when a device is notified. Device-specific hooks are provided for each of these situations, so a simple override is all that is needed to react:&lt;br /&gt;
&lt;br /&gt;
* Prior to saving the state of the system, all the devices are notified. This takes the place of registering handlers via &#039;&#039;&#039;state_save_register_presave&#039;&#039;&#039;() as was done previously. To hook this, simple override the &#039;&#039;&#039;device_pre_save&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* Similarly, immediately after loading a saved state, all devices are notified. Device-specific classes hook this via the &#039;&#039;&#039;device_post_load&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
* If the emulation is started with the debugger enabled, there is a hook &#039;&#039;&#039;device_debug_setup&#039;&#039;&#039;() which is called to allow device-specific classes to register additional functions or other information with the debugger.&lt;br /&gt;
&lt;br /&gt;
* Finally, if the clock of a device is changed, a notification is sent via the &#039;&#039;&#039;device_clock_changed&#039;&#039;&#039;() method. This is necessary because most clock management is handled generically in the base &#039;&#039;&#039;device_t&#039;&#039;&#039; class.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
* Static configs&lt;br /&gt;
* Inline configs&lt;br /&gt;
&lt;br /&gt;
=Interfaces in Detail=&lt;br /&gt;
&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
= Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3177</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3177"/>
		<updated>2010-05-19T19:57:19Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Runtime */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
Once the entire set of devices has been allocated, MAME will once again run through the list of devices one by one and request them to start. If a device has device-specific work to do at startup (such as allocating memory or consuming configuration information), it can override the &#039;&#039;&#039;device_start&#039;&#039;&#039;() method to do so. If a device has a dependency upon another device being started, and that other device isn&#039;t ready yet, you can throw a &#039;&#039;&#039;device_missing_dependencies&#039;&#039;&#039; exception from within the &#039;&#039;&#039;device_start&#039;&#039;&#039; function and you will be re-queued to the end of the initialization order.&lt;br /&gt;
&lt;br /&gt;
An important thing to note is the explicit separation between allocation and startup. All the devices are allocated first, and then all of them are started. The intention is that most of the hard work is done at start time, leaving the class constructor mostly the job of ensuring all local variables are initialized to sane values.&lt;br /&gt;
&lt;br /&gt;
After the devices are all allocated and started, MAME makes one more pass through them all to reset them. As with startup, a device-specific class can override the &#039;&#039;&#039;device_reset&#039;&#039;&#039;() method to hook into this notification. Unlike startup, which occurs exactly once, a reset may happen multiple times throughout a device&#039;s existence. In addition to the first call at startup, all devices are also implicitly reset when a soft or hard reset is performed by the user, or when a driver explicitly calls the device&#039;s &#039;&#039;&#039;reset&#039;&#039;&#039;() method.&lt;br /&gt;
&lt;br /&gt;
Finally, when the emulation is complete, all the devices are destructed. Note that there is no separation between stopping and destruction, as there is between starting and allocation. This means that your device&#039;s destructor is responsible for cleaning up any allocations or other side-effects created during the device&#039;s lifetime, excepting those allocated via the &#039;&#039;&#039;auto_alloc&#039;&#039;&#039; macros, which are automatically destroyed shortly afterwards.&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
* Static configs&lt;br /&gt;
* Inline configs&lt;br /&gt;
&lt;br /&gt;
=Interfaces in Detail=&lt;br /&gt;
&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
= Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3174</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3174"/>
		<updated>2010-05-18T21:09:03Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Runtime */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039;() method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
(more later)&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
* Static configs&lt;br /&gt;
* Inline configs&lt;br /&gt;
&lt;br /&gt;
=Interfaces in Detail=&lt;br /&gt;
&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
= Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3173</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3173"/>
		<updated>2010-05-18T21:08:46Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating a device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the &#039;&#039;&#039;device_process_token&#039;&#039;&#039;() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the &#039;&#039;&#039;device_validity_check&#039;&#039;&#039;() method and outputting errors if any are found. For this reason, validation should happen here rather than in the &#039;&#039;&#039;device_config_complete&#039;&#039;&#039;(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039; method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
(more later)&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
* Static configs&lt;br /&gt;
* Inline configs&lt;br /&gt;
&lt;br /&gt;
=Interfaces in Detail=&lt;br /&gt;
&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
= Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3172</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3172"/>
		<updated>2010-05-18T19:40:14Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Lifecycle of a Device */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
==Configuration==&lt;br /&gt;
&lt;br /&gt;
Machine configurations in MAME are represented by a tokenizing mechanism wrapped by macros. A typical machine driver looks something like this (having removed some of the irrelevant details):&lt;br /&gt;
&lt;br /&gt;
 static MACHINE_DRIVER_START( pacman )&lt;br /&gt;
     MDRV_CPU_ADD(&amp;quot;maincpu&amp;quot;, Z80, MASTER_CLOCK/6)&lt;br /&gt;
     MDRV_CPU_PROGRAM_MAP(pacman_map)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SCREEN_ADD(&amp;quot;screen&amp;quot;, RASTER)&lt;br /&gt;
     MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)&lt;br /&gt;
     ...&lt;br /&gt;
     MDRV_SOUND_ADD(&amp;quot;namco&amp;quot;, NAMCO, MASTER_CLOCK/6/32)&lt;br /&gt;
     MDRV_SOUND_CONFIG(namco_config)&lt;br /&gt;
     MDRV_SOUND_ROUTE(ALL_OUTPUTS, &amp;quot;mono&amp;quot;, 1.0)&lt;br /&gt;
 MACHINE_DRIVER_END&lt;br /&gt;
&lt;br /&gt;
When the compiler processes this, the MDRV_* macros all map down to a set of 32-bit or 64-bit integral tokens which are stored as a stream for later processing.&lt;br /&gt;
&lt;br /&gt;
It may not be immediately obvious, but the machine configuration above defines three separate devices: a CPU device called &amp;quot;maincpu&amp;quot;, a video screen device called &amp;quot;screen&amp;quot;, and a Namco sound device called &amp;quot;namco&amp;quot;. Each device generally defines its own MDRV_*_ADD() macro which permits some flexibility in how each device is added. The MDRV_* macros that follow each device provide configuration information. More on configuration in a later chapter.&lt;br /&gt;
&lt;br /&gt;
When a machine configuration is instantiated, it first takes the token stream and executes it, creating the device configuration whenever it sees an MCONFIG_TOKEN_DEVICE_ADD token (which is output by the MDRV_*_ADD() macro mentioned above), and populating the device configuration with data from subsequent macros.&lt;br /&gt;
&lt;br /&gt;
One of the parameters to MCONFIG_TOKEN_DEVICE_ADD is a device type. In MAME a device type is a static function pointer which serves as the factory function for allocating a device configuration. So when we need to add a device, we simply call the factory function and ask it to allocate for us a new device configuration of the appropriate type.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is allocated, we continue to process tokens. Tokens within a certain well-defined range are known to be device configuration tokens, and these are handed off to the allocated device configuration for processing. Specific devices can also support their own custom-defined tokens if they need special behaviors (the MDRV_SOUND_ROUTE above does this) by overriding the device_process_token() method in the device-specific configuration class.&lt;br /&gt;
&lt;br /&gt;
Upon encountering the end of the token stream, all the devices are notified that the configuration parsing is complete. This allows them to consolidate any configuration information or do any other work that needs to be done. Device-specific configuration classes can override the device_config_complete() method to hook into this event.&lt;br /&gt;
&lt;br /&gt;
There are several situations in which the machine configuration and all the device configurations are created: to perform validity checks on all the drivers; to output information needed by the -listxml and other front-end functions; to check for vector screens when parsing .ini files; and finally, in preparation for starting an actual game. In all cases but the last one, the machine and device configurations are created and discarded without ever creating any runtime devices, so the device lifecycle can very well begin and end with the device configuration.&lt;br /&gt;
&lt;br /&gt;
In the case where validity checks are performed, the device-specific configuration class has the option of performing its own validation by overriding the device_validity_check() method and outputting errors if any are found. For this reason, validation should happen here rather than in the device_config_complete(), so that errors can be reported in a consistent manner.&lt;br /&gt;
&lt;br /&gt;
==Runtime==&lt;br /&gt;
&lt;br /&gt;
When the time comes to create a running machine object and start up the devices, MAME will take the device list contained in the machine configuration and rip through it to allocate the runtime devices. The mechanism for allocating a runtime device is to call the device-specific configuration class&#039;s &#039;&#039;&#039;device_alloc&#039;&#039;&#039; method, whose job is simply to auto_alloc an instance of the device-specific runtime class. This method is a required override.&lt;br /&gt;
&lt;br /&gt;
(more later)&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
* Static configs&lt;br /&gt;
* Inline configs&lt;br /&gt;
&lt;br /&gt;
=Interfaces in Detail=&lt;br /&gt;
&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
= Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3171</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3171"/>
		<updated>2010-05-18T19:13:27Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Basic Concepts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;tag&#039;&#039; to identify the device instance, a &#039;&#039;clock&#039;&#039; value which represents the input clock to the device, and an &#039;&#039;owner&#039;&#039; who serves as the device&#039;s parent. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. This additional configuration data is stored in the device-specific class. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. The base &#039;&#039;&#039;device_t&#039;&#039;&#039; class provides a number of basic device concepts, including device initialization, reset, hooks into the save state system, clock scaling. It also holds a reference back to the corresponding &#039;&#039;&#039;device_config&#039;&#039;&#039; that begat the device.&lt;br /&gt;
&lt;br /&gt;
The device-specific runtime class, which is required to derive from &#039;&#039;&#039;device_t&#039;&#039;&#039;, then contains all the runtime state of the device, along with methods to operate upon the live device. It can also override several internal methods of its parent class to gain access to hooks that are called during specific events in the machine&#039;s lifecycle.&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
* Configuration&lt;br /&gt;
* Runtime&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
* Static configs&lt;br /&gt;
* Inline configs&lt;br /&gt;
&lt;br /&gt;
=Interfaces in Detail=&lt;br /&gt;
&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
= Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3170</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3170"/>
		<updated>2010-05-17T20:37:05Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Basic Concepts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;configuration class&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;runtime class&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;&#039;tag&#039;&#039;&#039; to identify the device instance, and a &#039;&#039;&#039;clock&#039;&#039;&#039; value which represents the input clock to the device. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. (More later)&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
* Configuration&lt;br /&gt;
* Runtime&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
* Static configs&lt;br /&gt;
* Inline configs&lt;br /&gt;
&lt;br /&gt;
=Interfaces in Detail=&lt;br /&gt;
&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
= Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3169</id>
		<title>MAME Device Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=MAME_Device_Basics&amp;diff=3169"/>
		<updated>2010-05-17T20:16:06Z</updated>

		<summary type="html">&lt;p&gt;Aaron: New page: =Overview=  In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
In MAME, a device is a mechanism for encapsulating behavior. While it is common to associate a device (in the MAME sense) with a physical device (in the real world), there does not necessarily need to be a 1:1 correspondance between the two.&lt;br /&gt;
&lt;br /&gt;
Devices are important because they provide clean hooks into the MAME system. They are notified when key things in the system change, they encode their own configuration information, keep their own state, and can be instantiated multiple times within a given machine. They are easily located via a simple string tag, and are first-class citizens in memory maps, so they are easily read from and written to.&lt;br /&gt;
&lt;br /&gt;
As of MAME 0.139, devices are implemented using a collection of C++ classes. In order to provide the flexibility necessary to describe the sorts of devices in MAME, the device model relies heavily on the &#039;&#039;multiple inheritance&#039;&#039; feature of C++ to extend devices with one or more &#039;&#039;device interfaces&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Basic Concepts=&lt;br /&gt;
&lt;br /&gt;
Every device in the project is built up out of two classes: a device-specific &#039;&#039;&#039;configuration class&#039;&#039;&#039; (derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class) and a device-specific &#039;&#039;&#039;runtime class&#039;&#039;&#039; (derived from the &#039;&#039;&#039;device_t&#039;&#039;&#039; class). &lt;br /&gt;
&lt;br /&gt;
The configuration class is responsible for encapsulating the device&#039;s configuration. The base &#039;&#039;&#039;device_config&#039;&#039;&#039; class automatically supports several core configuration properties, such as a short string &#039;&#039;&#039;tag&#039;&#039;&#039; to identify the device instance, and a &#039;&#039;&#039;clock&#039;&#039;&#039; value which represents the input clock to the device. All device-specific configuration classes must be derived from the &#039;&#039;&#039;device_config&#039;&#039;&#039; class at their root.&lt;br /&gt;
&lt;br /&gt;
Of course, most devices require more configuration than this, and so there are mechanisms for the device-specific configuration class to accept further configuration information, both inline in the MACHINE_CONFIG description, as well as externally in a static structure. More details on how this works come later in this article.&lt;br /&gt;
&lt;br /&gt;
In addition to holding the configuration of a device, the device-specific configuration class also serves as a &amp;quot;factory&amp;quot; class that provides a mechanism for the MAME core to instantiate both new configuration objects, via a static method, and new runtime objects, via a required virtual method. (It is worth noting that the pointer to the static method that constructs configuration objects also serves as the device &amp;quot;type&amp;quot;, which is a unique single entry point into the device.)&lt;br /&gt;
&lt;br /&gt;
The runtime class, as its name implies, holds the runtime state of a device. (More later)&lt;br /&gt;
&lt;br /&gt;
=Lifecycle of a Device=&lt;br /&gt;
&lt;br /&gt;
* Configuration&lt;br /&gt;
* Runtime&lt;br /&gt;
&lt;br /&gt;
=Configuring Devices=&lt;br /&gt;
&lt;br /&gt;
* Static configs&lt;br /&gt;
* Inline configs&lt;br /&gt;
&lt;br /&gt;
=Interfaces in Detail=&lt;br /&gt;
&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
= Best Practices=&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
	<entry>
		<id>https://wiki.mamedev.org/index.php?title=How_MAME_Works&amp;diff=3168</id>
		<title>How MAME Works</title>
		<link rel="alternate" type="text/html" href="https://wiki.mamedev.org/index.php?title=How_MAME_Works&amp;diff=3168"/>
		<updated>2010-05-17T19:55:40Z</updated>

		<summary type="html">&lt;p&gt;Aaron: /* Core Internals */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following is a list of documents describing the internal workings (core) of the MAME emulator.  Most are penned by Aaron Giles.&lt;br /&gt;
&lt;br /&gt;
== Building MAME ==&lt;br /&gt;
* [[Building MAME using Microsoft Visual Studio compilers]]&lt;br /&gt;
&lt;br /&gt;
== Writing for MAME ==&lt;br /&gt;
* [[Contributing to MAME]]&lt;br /&gt;
* [[Submitting Source Code]]&lt;br /&gt;
* [[MAME Coding Conventions]]&lt;br /&gt;
&lt;br /&gt;
== For Driver Writers ==&lt;br /&gt;
* [[Game Drivers]]&lt;br /&gt;
* [[Resource Management in MAME]]&lt;br /&gt;
* [[DIP Switches in MAME]]&lt;br /&gt;
* [[MAME Interrupt Function Review]]&lt;br /&gt;
* [[Using MAME&#039;s tilemap system]]&lt;br /&gt;
* [[Programmable Logic Devices in MAME]]&lt;br /&gt;
* [[CPUs and Address Spaces]]&lt;br /&gt;
* [[Address Maps]]&lt;br /&gt;
&lt;br /&gt;
== Core Internals ==&lt;br /&gt;
* [[MAME Devices]]&lt;br /&gt;
** [[All About Devices]] (out of date)&lt;br /&gt;
* [[Timers and timing]]&lt;br /&gt;
* [[Filters and streams in the MAME Sound System]]&lt;br /&gt;
* [[Save State Fundamentals]]&lt;br /&gt;
* [[Using the GFX/TileMap viewer (F4)]]&lt;br /&gt;
* [[How To Use the &#039;New&#039; Renderer]]&lt;br /&gt;
* [[Layouts and Rendering for MAME Artwork System]]&lt;br /&gt;
* [[LAY File Basics - Part I]]&lt;br /&gt;
&lt;br /&gt;
== CPU Emulation ==&lt;br /&gt;
* [[Virtual TLB]]&lt;br /&gt;
* [[CPU Scheduling in MAME]]&lt;br /&gt;
&lt;br /&gt;
== Universal Dynamic Recompiler ==&lt;br /&gt;
* [[Core Concepts]]&lt;br /&gt;
* [[UML Architecture]]&lt;br /&gt;
** [[UML Control Flow Opcodes]]&lt;br /&gt;
** [[UML Internal Register Opcodes]]&lt;br /&gt;
** [[UML Integer Opcodes]]&lt;br /&gt;
** [[UML Floating Point Opcodes]]&lt;br /&gt;
* [[Dynamic Recompiler Author&#039;s Guide]]&lt;br /&gt;
* [[Back-End Author&#039;s Guide]]&lt;br /&gt;
&lt;br /&gt;
== Tips &amp;amp; Tricks ==&lt;br /&gt;
* [[Executing Code Out of a Memory Region With a Read Handler]]&lt;br /&gt;
* [[Checklist for Cleaning Up Drivers]]&lt;br /&gt;
* [[Writing Messages to the Screen In a MAME Driver]]&lt;/div&gt;</summary>
		<author><name>Aaron</name></author>
	</entry>
</feed>