From: <m97...@us...> - 2010-11-27 11:59:21
|
Revision: 11765 http://openmsx.svn.sourceforge.net/openmsx/?rev=11765&view=rev Author: m9710797 Date: 2010-11-27 11:59:14 +0000 (Sat, 27 Nov 2010) Log Message: ----------- Extended MSXCPUInterface::testUnsetExpanded() to also work with MSXMultiMemDevice testUnsetExpanded() checks whether it's OK to remove a slotexpander. This is for example not allowed when there are still devices inserted in that expander. It's also possible to have one extension that is a combination of a slotexpander and already some devices in that expander. In such a case there can still be devices in the expander (but only those that are also part of the extension). testUnsetExpanded() mostly handled this fine. Though it went wrong with MSXMultiMemDevices. These are used when multiple MSXDevices share the same 16kB page in a certain (sub)slot. There was actually a TODO about this in the code. In practice MSXMultiMemDevices are rarely used, and even more rarely in slotexpanders. But it does occur in the recently added 'Boosted_audio' extension. Modified Paths: -------------- openmsx/trunk/src/cpu/MSXCPUInterface.cc openmsx/trunk/src/cpu/MSXMultiMemDevice.cc openmsx/trunk/src/cpu/MSXMultiMemDevice.hh Modified: openmsx/trunk/src/cpu/MSXCPUInterface.cc =================================================================== --- openmsx/trunk/src/cpu/MSXCPUInterface.cc 2010-11-26 18:03:40 UTC (rev 11764) +++ openmsx/trunk/src/cpu/MSXCPUInterface.cc 2010-11-27 11:59:14 UTC (rev 11765) @@ -331,18 +331,35 @@ std::set<MSXDevice*> allowed(alreadyRemoved.begin(), alreadyRemoved.end()); allowed.insert(dummyDevice.get()); assert(isExpanded(ps)); - if (expanded[ps] == 1) { - for (int ss = 0; ss < 4; ++ss) { - for (int page = 0; page < 4; ++page) { - if (allowed.find(slotLayout[ps][ss][page]) == - allowed.end()) { - throw MSXException( - "Can't remove slotexpander " - "because slot is still in use."); - } + if (expanded[ps] != 1) return; // ok, still expanded after this + + std::set<MSXDevice*> inUse; + for (int ss = 0; ss < 4; ++ss) { + for (int page = 0; page < 4; ++page) { + MSXDevice* device = slotLayout[ps][ss][page]; + std::set<MSXDevice*> devices; + if (MSXMultiMemDevice* memDev = dynamic_cast<MSXMultiMemDevice*>(device)) { + memDev->getDevices(devices); + } else { + devices.insert(device); } + std::set_difference(devices.begin(), devices.end(), + allowed.begin(), allowed.end(), + std::inserter(inUse, inUse.end())); + } } + if (inUse.empty()) return; // ok, no more devices in use + + StringOp::Builder msg; + msg << "Can't remove slot expander from slot " << ps + << " because the following devices are still inserted:"; + for (std::set<MSXDevice*>::const_iterator it = inUse.begin(); + it != inUse.end(); ++it) { + msg << " " << (*it)->getName(); + } + msg << '.'; + throw MSXException(msg); } void MSXCPUInterface::unsetExpanded(int ps) Modified: openmsx/trunk/src/cpu/MSXMultiMemDevice.cc =================================================================== --- openmsx/trunk/src/cpu/MSXMultiMemDevice.cc 2010-11-26 18:03:40 UTC (rev 11764) +++ openmsx/trunk/src/cpu/MSXMultiMemDevice.cc 2010-11-27 11:59:14 UTC (rev 11765) @@ -73,6 +73,13 @@ return ranges.size() == 1; } +void MSXMultiMemDevice::getDevices(std::set<MSXDevice*>& result) const +{ + for (unsigned i = 0; i < (ranges.size() - 1); ++i) { + result.insert(ranges[i].device); + } +} + std::string MSXMultiMemDevice::getName() const { assert(!empty()); Modified: openmsx/trunk/src/cpu/MSXMultiMemDevice.hh =================================================================== --- openmsx/trunk/src/cpu/MSXMultiMemDevice.hh 2010-11-26 18:03:40 UTC (rev 11764) +++ openmsx/trunk/src/cpu/MSXMultiMemDevice.hh 2010-11-27 11:59:14 UTC (rev 11765) @@ -5,6 +5,7 @@ #include "MSXMultiDevice.hh" #include <vector> +#include <set> namespace openmsx { @@ -20,6 +21,7 @@ bool add(MSXDevice& device, int base, int size); void remove(MSXDevice& device, int base, int size); bool empty() const; + void getDevices(std::set<MSXDevice*>& result) const; // MSXDevice virtual std::string getName() const; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |