1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
|
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
mconfig.c
Machine configuration macros and functions.
***************************************************************************/
#include "emu.h"
#include "emuopts.h"
#include "screen.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)
{
// add the root device
device_add(nullptr, "root", gamedrv.type, 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();
const char *slot_option_name = owner.tag() + 1;
// figure out which device goes into this slot
bool const has_option = options.has_slot_option(slot_option_name);
const char *selval;
bool is_default;
if (!has_option)
{
// The only time we should be getting here is when emuopts.cpp is invoking
// us to evaluate slot/image options, and the internal state of emuopts.cpp has
// not caught up yet
selval = slot.default_option();
is_default = true;
}
else
{
const slot_option &opt = options.slot_option(slot_option_name);
selval = opt.value().c_str();
is_default = !opt.specified();
}
if (selval && *selval)
{
device_slot_option const *const option = slot.option(selval);
if (option && (is_default || option->selectable()))
{
// create the device
device_t *new_dev = device_add(&owner, option->name(), option->devtype(), option->clock());
slot.set_card_device(new_dev);
char const *const default_bios = option->default_bios();
if (default_bios != nullptr)
new_dev->set_default_bios_tag(default_bios);
auto additions = option->machine_config();
if (additions)
additions(new_dev);
input_device_default const *const input_device_defaults = option->input_device_defaults();
if (input_device_defaults)
new_dev->set_input_default(input_device_defaults);
}
else
throw emu_fatalerror("Unknown slot option '%s' in slot '%s'", selval, owner.tag()+1);
}
}
// 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()
{
}
//-------------------------------------------------
// device_add - configuration helper to add a
// new device
//-------------------------------------------------
device_t *machine_config::device_add(device_t *owner, const char *tag, device_type type, u32 clock)
{
char const *const 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)
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)
{
// allocate the new device and append it to the owner's list
device_t *const device = &owner->subdevices().m_list.append(*type(*this, tag, owner, clock).release());
device->add_machine_configuration(*this);
return device;
}
else
{
// allocate the root device directly
assert(!m_root_device);
m_root_device = type(*this, tag, nullptr, clock);
driver_device *driver = dynamic_cast<driver_device *>(m_root_device.get());
if (driver)
driver->set_game_driver(m_gamedrv);
m_root_device->add_machine_configuration(*this);
return m_root_device.get();
}
}
//-------------------------------------------------
// 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, u32 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);
}
else
{
// 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 and substitute it for the old one in the owner's list
device_t *const new_device = &owner->subdevices().m_list.replace_and_remove(*type(*this, tag, owner, clock).release(), *old_device);
new_device->add_machine_configuration(*this);
return new_device;
}
}
device_t *machine_config::device_replace(device_t *owner, const char *tag, device_type type, const XTAL &clock)
{
std::string msg = std::string("Replacing device ") + tag;
clock.validate(msg);
return device_replace(owner, tag, type, clock.value());
}
//-------------------------------------------------
// 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);
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);
}
|