openMSX
HardwareConfig.cc
Go to the documentation of this file.
1 #include "HardwareConfig.hh"
2 #include "XMLLoader.hh"
3 #include "XMLException.hh"
4 #include "DeviceConfig.hh"
5 #include "XMLElement.hh"
6 #include "FileOperations.hh"
7 #include "MSXMotherBoard.hh"
9 #include "MSXCPUInterface.hh"
10 #include "CommandController.hh"
11 #include "DeviceFactory.hh"
12 #include "TclArgParser.hh"
13 #include "serialize.hh"
14 #include "serialize_stl.hh"
15 #include "unreachable.hh"
16 #include "view.hh"
17 #include "xrange.hh"
18 #include <cassert>
19 #include <iostream>
20 #include <memory>
21 
22 using std::move;
23 using std::string;
24 using std::string_view;
25 using std::unique_ptr;
26 using std::vector;
27 
28 namespace openmsx {
29 
30 unique_ptr<HardwareConfig> HardwareConfig::createMachineConfig(
31  MSXMotherBoard& motherBoard, string machineName)
32 {
33  auto result = std::make_unique<HardwareConfig>(
34  motherBoard, move(machineName));
35  result->type = HardwareConfig::Type::MACHINE;
36  result->load("machines");
37  return result;
38 }
39 
40 unique_ptr<HardwareConfig> HardwareConfig::createExtensionConfig(
41  MSXMotherBoard& motherBoard, string extensionName, string slotname)
42 {
43  auto result = std::make_unique<HardwareConfig>(
44  motherBoard, move(extensionName));
45  result->load("extensions");
46  result->setName(result->hwName);
47  result->type = HardwareConfig::Type::EXTENSION;
48  result->setSlot(move(slotname));
49  return result;
50 }
51 
52 unique_ptr<HardwareConfig> HardwareConfig::createRomConfig(
53  MSXMotherBoard& motherBoard, string romfile,
54  string slotname, span<const TclObject> options)
55 {
56  auto result = std::make_unique<HardwareConfig>(motherBoard, "rom");
57  result->setName(romfile);
58  result->type = HardwareConfig::Type::ROM;
59 
60  vector<string_view> ipsfiles;
61  string mapper;
62  ArgsInfo info[] = {
63  valueArg("-ips", ipsfiles),
64  valueArg("-romtype", mapper),
65  };
66  auto& interp = motherBoard.getCommandController().getInterpreter();
67  auto args = parseTclArgs(interp, options, info);
68  if (!args.empty()) {
69  throw MSXException("Invalid option \"", args.front().getString(), '\"');
70  }
71 
72  const auto& sramfile = FileOperations::getFilename(romfile);
73  auto context = userFileContext(strCat("roms/", sramfile));
74  for (const auto& ips : ipsfiles) {
75  if (!FileOperations::isRegularFile(context.resolve(ips))) {
76  throw MSXException("Invalid IPS file: ", ips);
77  }
78  }
79 
80  string resolvedFilename = FileOperations::getAbsolutePath(
81  context.resolve(romfile));
82  if (!FileOperations::isRegularFile(resolvedFilename)) {
83  throw MSXException("Invalid ROM file: ", resolvedFilename);
84  }
85 
86  XMLElement extension("extension");
87  auto& devices = extension.addChild("devices");
88  auto& primary = devices.addChild("primary");
89  primary.addAttribute("slot", slotname);
90  auto& secondary = primary.addChild("secondary");
91  secondary.addAttribute("slot", move(slotname));
92  auto& device = secondary.addChild("ROM");
93  device.addAttribute("id", "MSXRom");
94  auto& mem = device.addChild("mem");
95  mem.addAttribute("base", "0x0000");
96  mem.addAttribute("size", "0x10000");
97  auto& rom = device.addChild("rom");
98  rom.addChild("resolvedFilename", resolvedFilename);
99  rom.addChild("filename", romfile);
100  if (!ipsfiles.empty()) {
101  auto& patches = rom.addChild("patches");
102  for (auto& s : ipsfiles) {
103  patches.addChild("ips", string(s));
104  }
105  }
106  device.addChild("sound").addChild("volume", "9000");
107  device.addChild("mappertype", mapper.empty() ? "auto" : std::move(mapper));
108  device.addChild("sramname", strCat(sramfile, ".SRAM"));
109 
110  result->setConfig(move(extension));
111  result->setFileContext(move(context));
112  return result;
113 }
114 
115 HardwareConfig::HardwareConfig(MSXMotherBoard& motherBoard_, string hwName_)
116  : motherBoard(motherBoard_)
117  , hwName(move(hwName_))
118 {
119  for (auto ps : xrange(4)) {
120  for (auto ss : xrange(4)) {
121  externalSlots[ps][ss] = false;
122  }
123  externalPrimSlots[ps] = false;
124  expandedSlots[ps] = false;
125  allocatedPrimarySlots[ps] = false;
126  }
127  userName = motherBoard.getUserName(hwName);
128 }
129 
131 {
132  motherBoard.freeUserName(hwName, userName);
133 #ifndef NDEBUG
134  try {
135  testRemove();
136  } catch (MSXException& e) {
137  std::cerr << e.getMessage() << '\n';
138  UNREACHABLE;
139  }
140 #endif
141  while (!devices.empty()) {
142  motherBoard.removeDevice(*devices.back());
143  devices.pop_back();
144  }
145  auto& slotManager = motherBoard.getSlotManager();
146  for (auto ps : xrange(4)) {
147  for (auto ss : xrange(4)) {
148  if (externalSlots[ps][ss]) {
149  slotManager.removeExternalSlot(ps, ss);
150  }
151  }
152  if (externalPrimSlots[ps]) {
153  slotManager.removeExternalSlot(ps);
154  }
155  if (expandedSlots[ps]) {
156  motherBoard.getCPUInterface().unsetExpanded(ps);
157  }
158  if (allocatedPrimarySlots[ps]) {
159  slotManager.freePrimarySlot(ps, *this);
160  }
161  }
162 }
163 
165 {
166  std::vector<MSXDevice*> alreadyRemoved;
167  for (auto& dev : view::reverse(devices)) {
168  dev->testRemove(alreadyRemoved);
169  alreadyRemoved.push_back(dev.get());
170  }
171  auto& slotManager = motherBoard.getSlotManager();
172  for (auto ps : xrange(4)) {
173  for (auto ss : xrange(4)) {
174  if (externalSlots[ps][ss]) {
175  slotManager.testRemoveExternalSlot(ps, ss, *this);
176  }
177  }
178  if (externalPrimSlots[ps]) {
179  slotManager.testRemoveExternalSlot(ps, *this);
180  }
181  if (expandedSlots[ps]) {
182  motherBoard.getCPUInterface().testUnsetExpanded(
183  ps, alreadyRemoved);
184  }
185  }
186 }
187 
188 const XMLElement& HardwareConfig::getDevicesElem() const
189 {
190  return getConfig().getChild("devices");
191 }
192 
193 static XMLElement loadHelper(const string& filename)
194 {
195  try {
196  return XMLLoader::load(filename, "msxconfig2.dtd");
197  } catch (XMLException& e) {
198  throw MSXException(
199  "Loading of hardware configuration failed: ",
200  e.getMessage());
201  }
202 }
203 
204 static string getFilename(string_view type, string_view name)
205 {
206  auto context = systemFileContext();
207  try {
208  // try <name>.xml
209  return context.resolve(FileOperations::join(
210  type, strCat(name, ".xml")));
211  } catch (MSXException& e) {
212  // backwards-compatibility:
213  // also try <name>/hardwareconfig.xml
214  try {
215  return context.resolve(FileOperations::join(
216  type, name, "hardwareconfig.xml"));
217  } catch (MSXException&) {
218  throw e; // signal first error
219  }
220  }
221 }
222 
223 XMLElement HardwareConfig::loadConfig(string_view type_, string_view name)
224 {
225  return loadHelper(getFilename(type_, name));
226 }
227 
228 void HardwareConfig::load(string_view type_)
229 {
230  string filename = getFilename(type_, hwName);
231  setConfig(loadHelper(filename));
232 
233  assert(!userName.empty());
234  const auto& dirname = FileOperations::getDirName(filename);
235  setFileContext(configFileContext(dirname, hwName, userName));
236 }
237 
239 {
240  // TODO this code does parsing for both 'expanded' and 'external' slots
241  // once machine and extensions are parsed separately move parsing
242  // of 'expanded' to MSXCPUInterface
243  //
244  for (auto& psElem : getDevicesElem().getChildren("primary")) {
245  const auto& primSlot = psElem->getAttribute("slot");
246  int ps = CartridgeSlotManager::getSlotNum(primSlot);
247  if (psElem->getAttributeAsBool("external", false)) {
248  if (ps < 0) {
249  throw MSXException(
250  "Cannot mark unspecified primary slot '",
251  primSlot, "' as external");
252  }
253  if (psElem->hasChildren()) {
254  throw MSXException(
255  "Primary slot ", ps,
256  " is marked as external, but that would only "
257  "make sense if its <primary> tag would be "
258  "empty.");
259  }
260  createExternalSlot(ps);
261  continue;
262  }
263  for (auto& ssElem : psElem->getChildren("secondary")) {
264  const auto& secSlot = ssElem->getAttribute("slot");
265  int ss = CartridgeSlotManager::getSlotNum(secSlot);
266  if ((-16 <= ss) && (ss <= -1) && (ss != ps)) {
267  throw MSXException(
268  "Invalid secondary slot specification: \"",
269  secSlot, "\".");
270  }
271  if (ss < 0) {
272  if ((ss >= -128) && (0 <= ps) && (ps < 4) &&
273  motherBoard.getCPUInterface().isExpanded(ps)) {
274  ss += 128;
275  } else {
276  continue;
277  }
278  }
279  if (ps < 0) {
280  if (ps == -256) {
281  ps = getAnyFreePrimarySlot();
282  } else {
283  ps = getSpecificFreePrimarySlot(-ps - 1);
284  }
285  auto mutableElem = const_cast<XMLElement*>(psElem);
286  mutableElem->setAttribute("slot", strCat(ps));
287  }
288  createExpandedSlot(ps);
289  if (ssElem->getAttributeAsBool("external", false)) {
290  if (ssElem->hasChildren()) {
291  throw MSXException(
292  "Secondary slot ", ps, '-', ss,
293  " is marked as external, but that would "
294  "only make sense if its <secondary> tag "
295  "would be empty.");
296  }
297  createExternalSlot(ps, ss);
298  }
299  }
300  }
301 }
302 
304 {
305  byte initialPrimarySlots = 0;
306  if (auto* slotmap = getConfig().findChild("slotmap")) {
307  for (auto* child : slotmap->getChildren("map")) {
308  int page = child->getAttributeAsInt("page", -1);
309  if (page < 0 || page > 3) {
310  throw MSXException("Invalid or missing page in slotmap entry");
311  }
312  int slot = child->getAttributeAsInt("slot", -1);
313  if (slot < 0 || slot > 3) {
314  throw MSXException("Invalid or missing slot in slotmap entry");
315  }
316  unsigned offset = page * 2;
317  initialPrimarySlots &= ~(3 << offset);
318  initialPrimarySlots |= slot << offset;
319  }
320  }
321  return initialPrimarySlots;
322 }
323 
325 {
326  createDevices(getDevicesElem(), nullptr, nullptr);
327 }
328 
330  const XMLElement* primary, const XMLElement* secondary)
331 {
332  for (auto& c : elem.getChildren()) {
333  const auto& childName = c.getName();
334  if (childName == "primary") {
335  createDevices(c, &c, secondary);
336  } else if (childName == "secondary") {
337  createDevices(c, primary, &c);
338  } else {
339  auto device = DeviceFactory::create(
340  DeviceConfig(*this, c, primary, secondary));
341  if (device) {
342  addDevice(move(device));
343  } else {
344  // device is nullptr, so we are apparently ignoring it on purpose
345  }
346  }
347  }
348 }
349 
350 void HardwareConfig::createExternalSlot(int ps)
351 {
352  motherBoard.getSlotManager().createExternalSlot(ps);
353  assert(!externalPrimSlots[ps]);
354  externalPrimSlots[ps] = true;
355 }
356 
357 void HardwareConfig::createExternalSlot(int ps, int ss)
358 {
359  motherBoard.getSlotManager().createExternalSlot(ps, ss);
360  assert(!externalSlots[ps][ss]);
361  externalSlots[ps][ss] = true;
362 }
363 
364 void HardwareConfig::createExpandedSlot(int ps)
365 {
366  if (!expandedSlots[ps]) {
367  motherBoard.getCPUInterface().setExpanded(ps);
368  expandedSlots[ps] = true;
369  }
370 }
371 
372 int HardwareConfig::getAnyFreePrimarySlot()
373 {
374  int ps = motherBoard.getSlotManager().allocateAnyPrimarySlot(*this);
375  assert(!allocatedPrimarySlots[ps]);
376  allocatedPrimarySlots[ps] = true;
377  return ps;
378 }
379 
380 int HardwareConfig::getSpecificFreePrimarySlot(unsigned slot)
381 {
382  int ps = motherBoard.getSlotManager().allocateSpecificPrimarySlot(slot, *this);
383  assert(!allocatedPrimarySlots[ps]);
384  allocatedPrimarySlots[ps] = true;
385  return ps;
386 }
387 
388 void HardwareConfig::addDevice(std::unique_ptr<MSXDevice> device)
389 {
390  motherBoard.addDevice(*device);
391  devices.push_back(move(device));
392 }
393 
394 void HardwareConfig::setName(string_view proposedName)
395 {
396  if (!motherBoard.findExtension(proposedName)) {
397  name = proposedName;
398  } else {
399  unsigned n = 0;
400  do {
401  name = strCat(proposedName, " (", ++n, ')');
402  } while (motherBoard.findExtension(name));
403  }
404 }
405 
406 void HardwareConfig::setSlot(string slotname)
407 {
408  for (auto& psElem : getDevicesElem().getChildren("primary")) {
409  const auto& primSlot = psElem->getAttribute("slot");
410  if (primSlot == "any") {
411  auto& mutableElem = const_cast<XMLElement*&>(psElem);
412  mutableElem->setAttribute("slot", move(slotname));
413  }
414  }
415 }
416 
417 static std::initializer_list<enum_string<HardwareConfig::Type>> configTypeInfo = {
418  { "MACHINE", HardwareConfig::Type::MACHINE },
419  { "EXTENSION", HardwareConfig::Type::EXTENSION },
420  { "ROM", HardwareConfig::Type::ROM },
421 };
423 
424 // version 1: initial version
425 // version 2: moved FileContext here (was part of config)
426 // version 3: hold 'config' by-value instead of by-pointer
427 // version 4: hold 'context' by-value instead of by-pointer
428 // version 5: added hwconfig type info
429 template<typename Archive>
430 void HardwareConfig::serialize(Archive& ar, unsigned version)
431 {
432  // filled-in by constructor:
433  // motherBoard, hwName, userName
434  // filled-in by parseSlots()
435  // externalSlots, externalPrimSlots, expandedSlots, allocatedPrimarySlots
436 
437  if (ar.versionBelow(version, 2)) {
438  XMLElement::getLastSerializedFileContext(); // clear any previous value
439  }
440  ar.serialize("config", config); // fills in getLastSerializedFileContext()
441  if (ar.versionAtLeast(version, 2)) {
442  if (ar.versionAtLeast(version, 4)) {
443  ar.serialize("context", context);
444  } else {
445  std::unique_ptr<FileContext> ctxt;
446  ar.serialize("context", ctxt);
447  if (ctxt) context = *ctxt;
448  }
449  } else {
451  assert(ctxt);
452  context = *ctxt;
453  }
454  if (ar.isLoader()) {
455  if (!motherBoard.getMachineConfig()) {
456  // must be done before parseSlots()
457  motherBoard.setMachineConfig(this);
458  } else {
459  // already set because this is an extension
460  }
461  parseSlots();
462  createDevices();
463  }
464  // only (polymorphically) initialize devices, they are already created
465  for (auto& d : devices) {
466  ar.serializePolymorphic("device", *d);
467  }
468  ar.serialize("name", name);
469  if (ar.versionAtLeast(version, 5)) {
470  ar.serialize("type", type);
471  } else {
472  assert(ar.isLoader());
474  }
475 }
477 
478 } // namespace openmsx
openmsx::MSXMotherBoard::findExtension
HardwareConfig * findExtension(std::string_view extensionName)
Definition: MSXMotherBoard.cc:366
openmsx::HardwareConfig::createMachineConfig
static std::unique_ptr< HardwareConfig > createMachineConfig(MSXMotherBoard &motherBoard, std::string machineName)
Definition: HardwareConfig.cc:30
openmsx::HardwareConfig::Type
Type
Definition: HardwareConfig.hh:24
HardwareConfig.hh
openmsx::HardwareConfig::~HardwareConfig
~HardwareConfig()
Definition: HardwareConfig.cc:130
openmsx::MSXMotherBoard::getSlotManager
CartridgeSlotManager & getSlotManager()
Definition: MSXMotherBoard.hh:122
xrange
auto xrange(T e)
Definition: xrange.hh:170
openmsx::CommandController::getInterpreter
virtual Interpreter & getInterpreter()=0
openmsx::CartridgeSlotManager::allocateAnyPrimarySlot
int allocateAnyPrimarySlot(const HardwareConfig &hwConfig)
Definition: CartridgeSlotManager.cc:202
openmsx::CartridgeSlotManager::testRemoveExternalSlot
void testRemoveExternalSlot(int ps, const HardwareConfig &allowed) const
Definition: CartridgeSlotManager.cc:121
serialize.hh
openmsx::CartridgeSlotManager::getSlotNum
static int getSlotNum(std::string_view slot)
Definition: CartridgeSlotManager.cc:58
openmsx::CartridgeSlotManager::removeExternalSlot
void removeExternalSlot(int ps)
Definition: CartridgeSlotManager.cc:136
openmsx::HardwareConfig::createDevices
void createDevices()
Definition: HardwareConfig.cc:324
openmsx::FileContext::resolve
std::string resolve(std::string_view filename) const
Definition: FileContext.cc:80
XMLException.hh
openmsx::SERIALIZE_ENUM
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
openmsx::FileOperations::getAbsolutePath
string getAbsolutePath(string_view path)
Transform given path into an absolute path.
Definition: FileOperations.cc:480
openmsx::FileOperations::isRegularFile
bool isRegularFile(const Stat &st)
Definition: FileOperations.cc:644
openmsx::XMLElement
XMLElement
Definition: XMLElement.cc:350
openmsx::MSXCPUInterface::isExpanded
bool isExpanded(int ps) const
Definition: MSXCPUInterface.hh:248
openmsx::MSXMotherBoard::addDevice
void addDevice(MSXDevice &device)
All MSXDevices should be registered by the MotherBoard.
Definition: MSXMotherBoard.cc:554
openmsx::MSXException
Definition: MSXException.hh:10
openmsx::HardwareConfig::parseSlotMap
byte parseSlotMap() const
Parses a slot mapping.
Definition: HardwareConfig.cc:303
openmsx::ArgsInfo
Definition: TclArgParser.hh:66
openmsx::userFileContext
FileContext userFileContext(string_view savePath)
Definition: FileContext.cc:164
XMLElement.hh
openmsx::XMLElement::addChild
XMLElement & addChild(std::string name)
Definition: XMLElement.cc:20
openmsx::MSXMotherBoard::removeDevice
void removeDevice(MSXDevice &device)
Definition: MSXMotherBoard.cc:559
openmsx::FileOperations::join
string join(string_view part1, string_view part2)
Join two paths.
Definition: FileOperations.cc:423
openmsx::MSXMotherBoard::getCommandController
CommandController & getCommandController()
Definition: MSXMotherBoard.cc:493
openmsx::HardwareConfig::HardwareConfig
HardwareConfig(const HardwareConfig &)=delete
openmsx::HardwareConfig::getConfig
const XMLElement & getConfig() const
Definition: HardwareConfig.hh:52
openmsx::MSXMotherBoard::setMachineConfig
void setMachineConfig(HardwareConfig *machineConfig)
Definition: MSXMotherBoard.cc:275
span
Definition: span.hh:126
openmsx::MSXCPUInterface::testUnsetExpanded
void testUnsetExpanded(int ps, std::vector< MSXDevice * > allowed) const
Definition: MSXCPUInterface.cc:259
CommandController.hh
TclArgParser.hh
openmsx::FileOperations::getDirName
string_view getDirName(string_view path)
Returns the directory portion of a path.
Definition: FileOperations.cc:398
UNREACHABLE
#define UNREACHABLE
Definition: unreachable.hh:38
openmsx::XMLElement
Definition: XMLElement.hh:16
XMLLoader.hh
openmsx::HardwareConfig::Type::ROM
@ ROM
openmsx::XMLElement::getLastSerializedFileContext
static std::unique_ptr< FileContext > getLastSerializedFileContext()
Definition: XMLElement.cc:316
openmsx::MSXMotherBoard
Definition: MSXMotherBoard.hh:61
openmsx::filename
constexpr const char *const filename
Definition: FirmwareSwitch.cc:10
openmsx::HardwareConfig::createRomConfig
static std::unique_ptr< HardwareConfig > createRomConfig(MSXMotherBoard &motherBoard, std::string romfile, std::string slotname, span< const TclObject > options)
Definition: HardwareConfig.cc:52
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::HardwareConfig::createExtensionConfig
static std::unique_ptr< HardwareConfig > createExtensionConfig(MSXMotherBoard &motherBoard, std::string extensionName, std::string slotname)
Definition: HardwareConfig.cc:40
openmsx::HardwareConfig::Type::EXTENSION
@ EXTENSION
serialize_stl.hh
view.hh
openmsx::DeviceFactory::create
static std::unique_ptr< MSXDevice > create(const DeviceConfig &conf)
Definition: DeviceFactory.cc:131
openmsx::XMLLoader::load
XMLElement load(string_view filename, string_view systemID)
Definition: XMLLoader.cc:34
openmsx::HardwareConfig::setFileContext
void setFileContext(FileContext &&ctxt)
Definition: HardwareConfig.hh:50
FileOperations.hh
openmsx::CartridgeSlotManager::createExternalSlot
void createExternalSlot(int ps)
Definition: CartridgeSlotManager.cc:78
openmsx::MSXMotherBoard::getUserName
std::string getUserName(const std::string &hwName)
Keep track of which 'usernames' are in use.
Definition: MSXMotherBoard.cc:708
gl::context
std::unique_ptr< Context > context
Definition: GLContext.cc:9
openmsx::MSXMotherBoard::getCPUInterface
MSXCPUInterface & getCPUInterface()
Definition: MSXMotherBoard.cc:404
MSXCPUInterface.hh
openmsx::MSXCPUInterface::unsetExpanded
void unsetExpanded(int ps)
Definition: MSXCPUInterface.cc:299
openmsx::HardwareConfig::Type::MACHINE
@ MACHINE
openmsx::parseTclArgs
std::vector< TclObject > parseTclArgs(Interpreter &interp, span< const TclObject > inArgs, span< const ArgsInfo > table)
Definition: commands/TclArgParser.cc:11
openmsx::MSXMotherBoard::getMachineConfig
const HardwareConfig * getMachineConfig() const
Definition: MSXMotherBoard.hh:101
openmsx::HardwareConfig
Definition: HardwareConfig.hh:22
CartridgeSlotManager.hh
openmsx::HardwareConfig::serialize
void serialize(Archive &ar, unsigned version)
Definition: HardwareConfig.cc:430
openmsx::CartridgeSlotManager::allocateSpecificPrimarySlot
int allocateSpecificPrimarySlot(unsigned slot, const HardwareConfig &hwConfig)
Definition: CartridgeSlotManager.cc:165
openmsx::HardwareConfig::testRemove
void testRemove() const
Checks whether this HardwareConfig can be deleted.
Definition: HardwareConfig.cc:164
openmsx::valueArg
ArgsInfo valueArg(std::string_view name, T &value)
Definition: TclArgParser.hh:85
view::reverse
auto reverse(Range &&range)
Definition: view.hh:300
unreachable.hh
DeviceConfig.hh
openmsx::MSXException::getMessage
const std::string & getMessage() const &
Definition: MSXException.hh:23
DeviceFactory.hh
openmsx::MSXCPUInterface::setExpanded
void setExpanded(int ps)
Definition: MSXCPUInterface.cc:245
openmsx::configFileContext
FileContext configFileContext(string_view path, string_view hwDescr, string_view userName)
Definition: FileContext.cc:145
strCat
std::string strCat(Ts &&...ts)
Definition: strCat.hh:573
openmsx::XMLElement::getChildren
const Children & getChildren() const
Definition: XMLElement.hh:59
openmsx::XMLElement::setAttribute
void setAttribute(std::string_view name, std::string value)
Definition: XMLElement.cc:58
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
MSXMotherBoard.hh
openmsx::HardwareConfig::loadConfig
static XMLElement loadConfig(std::string_view type, std::string_view name)
Definition: HardwareConfig.cc:223
xrange.hh
openmsx::MSXMotherBoard::freeUserName
void freeUserName(const std::string &hwName, const std::string &userName)
Definition: MSXMotherBoard.cc:720
openmsx::XMLElement::getChild
const XMLElement & getChild(std::string_view childName) const
Definition: XMLElement.cc:141
openmsx::HardwareConfig::parseSlots
void parseSlots()
Definition: HardwareConfig.cc:238
openmsx::systemFileContext
FileContext systemFileContext()
Definition: FileContext.cc:152
openmsx::FileOperations::getFilename
string_view getFilename(string_view path)
Returns the file portion of a path name.
Definition: FileOperations.cc:390