summaryrefslogblamecommitdiffstatshomepage
path: root/src/emu/mconfig.cpp
blob: e201558f2c977c348bd7ac8bab29e189da287779 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                





                                                                            

                                                                            
                
                    

                  
 







                                                                            
                                                                                
                                            
                                          
                                   
                                  
 
                               
                                                           
 
                                                                                      
                                                                                           
 
                                                                                  
         
                                                
                                   


                                                                                            

                                                             
 
                                    
                 
                                                                                       

                                                                          
                         


                                                                                                                           
                                                            


                                                                                                      
                                                         
                                                                                                            



                                                                                                                    
                         
                            
                                                                                                                             

                 
 
                                             
                                                                
 
                                                                       


                                                               


 


                                                   
 
                                 
 


 
                                                   



                                                   
                                                   
 
                                                             



                                                   

                                              
                                                   
 
                                                                                                      
 
                                   




                                                              
                                            






                                                    
                                                

                                                       
                                                                                                      
                                                                                                

                             
                               
 
                             


                                                                     
 


                                                                                      
 



                                                                 
 
 
 
                                                   
                                            

                                                   
 
                                                                                                          
 
                                                                
                                 

                                                     
         
                                                                                                     

                                                           
 











                                                                                                           
 
 
 
                                                   
                                           

                                                   
 
                                                                         
 
                                                                
                                 
                                                 
                              
         
                                                                                                    
                               

         






                                                          
                                             
                                                   
                       
 
 
 
                                                   
                                         

                                                   
 
                                                                       
 
                                                                
                                 
                                                 

                                  
                                                                          

                            
                      
 









                                                                    

                                                                      

















                                                                                 
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    mconfig.c

    Machine configuration macros and functions.

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

#include "emu.h"
#include "emuopts.h"
#include <ctype.h>


//**************************************************************************
//  MACHINE CONFIGURATIONS
//**************************************************************************

//-------------------------------------------------
//  machine_config - constructor
//-------------------------------------------------

machine_config::machine_config(const game_driver &gamedrv, emu_options &options)
	: m_minimum_quantum(attotime::zero),
		m_default_layout(nullptr),
		m_gamedrv(gamedrv),
		m_options(options)
{
	// construct the config
	(*gamedrv.machine_config)(*this, nullptr, nullptr);

	bool is_selected_driver = core_stricmp(gamedrv.name,options.system_name())==0;
	// intialize slot devices - make sure that any required devices have been allocated

	for (device_slot_interface &slot : slot_interface_iterator(root_device()))
	{
		device_t &owner = slot.device();
		std::string selval;
		bool isdefault = (options.priority(owner.tag()+1)==OPTION_PRIORITY_DEFAULT);
		if (is_selected_driver && options.exists(owner.tag()+1))
			selval = options.main_value(owner.tag()+1);
		else if (slot.default_option() != nullptr)
			selval.assign(slot.default_option());

		if (!selval.empty())
		{
			const device_slot_option *option = slot.option(selval.c_str());

			if (option && (isdefault || option->selectable()))
			{
				device_t *new_dev = device_add(&owner, option->name(), option->devtype(), option->clock());

				const char *default_bios = option->default_bios();
				if (default_bios != nullptr)
					device_t::static_set_default_bios_tag(*new_dev, default_bios);

				machine_config_constructor additions = option->machine_config();
				if (additions != nullptr)
					(*additions)(const_cast<machine_config &>(*this), new_dev, new_dev);

				const input_device_default *input_device_defaults = option->input_device_defaults();
				if (input_device_defaults)
					device_t::static_set_input_default(*new_dev, input_device_defaults);
			}
			else
				throw emu_fatalerror("Unknown slot option '%s' in slot '%s'", selval.c_str(), owner.tag()+1);
		}
	}

	// when finished, set the game driver
	driver_device::static_set_game(*m_root_device, gamedrv);

	// then notify all devices that their configuration is complete
	for (device_t &device : device_iterator(root_device()))
		if (!device.configured())
			device.config_complete();
}


//-------------------------------------------------
//  ~machine_config - destructor
//-------------------------------------------------

machine_config::~machine_config()
{
}


//-------------------------------------------------
//  first_screen - return a pointer to the first
//  screen device
//-------------------------------------------------

screen_device *machine_config::first_screen() const
{
	return screen_device_iterator(root_device()).first();
}


//-------------------------------------------------
//  device_add - configuration helper to add a
//  new device
//-------------------------------------------------

device_t *machine_config::device_add(device_t *owner, const char *tag, device_type type, UINT32 clock)
{
	const char *orig_tag = tag;

	// if the device path is absolute, start from the root
	if (tag[0] == ':')
	{
		tag++;
		owner = m_root_device.get();
	}

	// go down the path until we're done with it
	while (strchr(tag, ':'))
	{
		const char *next = strchr(tag, ':');
		assert(next != tag);
		std::string part(tag, next-tag);
		owner = owner->subdevices().find(part);
		if (owner == nullptr)
			throw emu_fatalerror("Could not find %s when looking up path for device %s\n",
									part.c_str(), orig_tag);
		tag = next+1;
	}
	assert(tag[0] != '\0');

	if (owner != nullptr)
	{
		// allocate the new device
		device_t *device = (*type)(*this, tag, owner, clock);

		// append it to the owner's list
		return &config_new_device(owner->subdevices().m_list.append(*device));
	}

	// allocate the root device directly
	assert(m_root_device == nullptr);
	m_root_device.reset((*type)(*this, tag, nullptr, clock));
	return &config_new_device(*m_root_device);
}


//-------------------------------------------------
//  device_replace - configuration helper to
//  replace one device with a new device
//-------------------------------------------------

device_t *machine_config::device_replace(device_t *owner, const char *tag, device_type type, UINT32 clock)
{
	// find the original device by relative tag (must exist)
	assert(owner != nullptr);
	device_t *old_device = owner->subdevice(tag);
	if (old_device == nullptr)
	{
		osd_printf_warning("Warning: attempting to replace non-existent device '%s'\n", tag);
		return device_add(owner, tag, type, clock);
	}

	// make sure we have the old device's actual owner
	owner = old_device->owner();
	assert(owner != nullptr);

	// remove references to the old device
	remove_references(*old_device);

	// allocate the new device
	device_t *new_device = (*type)(*this, tag, owner, clock);

	// substitute it for the old one in the owner's list
	return &config_new_device(owner->subdevices().m_list.replace_and_remove(*new_device, *old_device));
}


//-------------------------------------------------
//  device_remove - configuration helper to
//  remove a device
//-------------------------------------------------

device_t *machine_config::device_remove(device_t *owner, const char *tag)
{
	// find the original device by relative tag (must exist)
	assert(owner != nullptr);
	device_t *device = owner->subdevice(tag);
	if (device == nullptr)
	{
		osd_printf_warning("Warning: attempting to remove non-existent device '%s'\n", tag);
		return nullptr;
	}

	// make sure we have the old device's actual owner
	owner = device->owner();
	assert(owner != nullptr);

	// remove references to the old device
	remove_references(*device);

	// let the device's owner do the work
	owner->subdevices().m_list.remove(*device);
	return nullptr;
}


//-------------------------------------------------
//  device_find - configuration helper to
//  locate a device
//-------------------------------------------------

device_t *machine_config::device_find(device_t *owner, const char *tag)
{
	// find the original device by relative tag (must exist)
	assert(owner != nullptr);
	device_t *device = owner->subdevice(tag);
	assert(device != nullptr);
	if (device == nullptr)
		throw emu_fatalerror("Unable to find device '%s'\n", tag);

	// return the device
	return device;
}


//-------------------------------------------------
//  remove_references - globally remove references
//  to a device about to be removed from the tree
//-------------------------------------------------

void machine_config::remove_references(ATTR_UNUSED device_t &device)
{
	// iterate over all devices and remove any references
	for (device_t &scan : device_iterator(root_device()))
		scan.subdevices().m_tagmap.clear(); //remove(&device);
}


//-------------------------------------------------
//  config_new_device - helper for recursive
//  configuration of newly added devices
//-------------------------------------------------

device_t &machine_config::config_new_device(device_t &device)
{
	// apply any machine configuration owned by the device now
	machine_config_constructor additions = device.machine_config_additions();
	if (additions != nullptr)
		(*additions)(*this, &device, nullptr);

	// return the new device
	return device;
}