mirror of
https://github.com/holub/mame
synced 2025-05-30 17:41:47 +03:00
219 lines
6.5 KiB
C
219 lines
6.5 KiB
C
// 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_watchdog_vblank_count(0),
|
|
m_watchdog_time(attotime::zero),
|
|
m_nvram_handler(NULL),
|
|
m_memcard_handler(NULL),
|
|
m_video_attributes(0),
|
|
m_default_layout(NULL),
|
|
m_gamedrv(gamedrv),
|
|
m_options(options),
|
|
m_root_device(NULL)
|
|
{
|
|
// construct the config
|
|
(*gamedrv.machine_config)(*this, NULL, NULL);
|
|
|
|
bool is_selected_driver = mame_stricmp(gamedrv.name,options.system_name())==0;
|
|
// intialize slot devices - make sure that any required devices have been allocated
|
|
slot_interface_iterator slotiter(root_device());
|
|
for (device_slot_interface *slot = slotiter.first(); slot != NULL; slot = slotiter.next())
|
|
{
|
|
device_t &owner = slot->device();
|
|
astring temp;
|
|
const char *selval = options.main_value(temp, owner.tag()+1);
|
|
bool isdefault = (options.priority(owner.tag()+1)==OPTION_PRIORITY_DEFAULT);
|
|
if (!is_selected_driver || !options.exists(owner.tag()+1))
|
|
selval = slot->default_option();
|
|
|
|
if (selval != NULL && *selval != 0)
|
|
{
|
|
const device_slot_option *option = slot->option(selval);
|
|
|
|
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 != NULL)
|
|
device_t::static_set_default_bios_tag(*new_dev, default_bios);
|
|
|
|
machine_config_constructor additions = option->machine_config();
|
|
if (additions != NULL)
|
|
(*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, 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
|
|
device_iterator iter(root_device());
|
|
for (device_t *device = iter.first(); device != NULL; device = iter.next())
|
|
if (!device->configured())
|
|
device->config_complete();
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// ~machine_config - destructor
|
|
//-------------------------------------------------
|
|
|
|
machine_config::~machine_config()
|
|
{
|
|
global_free(m_root_device);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// first_screen - return a pointer to the first
|
|
// screen device
|
|
//-------------------------------------------------
|
|
|
|
screen_device *machine_config::first_screen() const
|
|
{
|
|
screen_device_iterator iter(root_device());
|
|
return iter.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;
|
|
}
|
|
|
|
// go down the path until we're done with it
|
|
while (strchr(tag, ':'))
|
|
{
|
|
const char *next = strchr(tag, ':');
|
|
assert(next != tag);
|
|
astring part(tag, next-tag);
|
|
device_t *curdevice;
|
|
for (curdevice = owner->m_subdevice_list.first(); curdevice != NULL; curdevice = curdevice->next())
|
|
if (part == curdevice->m_basetag)
|
|
break;
|
|
if (!curdevice)
|
|
throw emu_fatalerror("Could not find %s when looking up path for device %s\n",
|
|
part.cstr(), orig_tag);
|
|
owner = curdevice;
|
|
tag = next+1;
|
|
}
|
|
assert(tag[0]);
|
|
|
|
// if there's an owner, let the owner do the work
|
|
if (owner != NULL)
|
|
return owner->add_subdevice(type, tag, clock);
|
|
|
|
// otherwise, allocate the device directly
|
|
assert(m_root_device == NULL);
|
|
m_root_device = (*type)(*this, tag, owner, clock);
|
|
|
|
// apply any machine configuration owned by the device now
|
|
machine_config_constructor additions = m_root_device->machine_config_additions();
|
|
if (additions != NULL)
|
|
(*additions)(*this, m_root_device, NULL);
|
|
return 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 this name (must exist)
|
|
assert(owner != NULL);
|
|
device_t *device = owner->subdevice(tag);
|
|
if (device == NULL)
|
|
{
|
|
mame_printf_warning("Warning: attempting to replace non-existent device '%s'\n", tag);
|
|
return device_add(owner, tag, type, clock);
|
|
}
|
|
|
|
// let the device's owner do the work
|
|
return device->owner()->replace_subdevice(*device, type, tag, clock);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// 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 this name (must exist)
|
|
assert(owner != NULL);
|
|
device_t *device = owner->subdevice(tag);
|
|
if (device == NULL)
|
|
{
|
|
mame_printf_warning("Warning: attempting to remove non-existent device '%s'\n", tag);
|
|
return NULL;
|
|
}
|
|
|
|
// let the device's owner do the work
|
|
device->owner()->remove_subdevice(*device);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// 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 this name (must exist)
|
|
assert(owner != NULL);
|
|
device_t *device = owner->subdevice(tag);
|
|
assert(device != NULL);
|
|
if (device == NULL)
|
|
throw emu_fatalerror("Unable to find device '%s'\n", tag);
|
|
|
|
// return the device
|
|
return device;
|
|
}
|