23 : deviceConfig(config)
29 : deviceConfig(config)
34 void MSXDevice::initName(std::string_view name)
59 assert(referencedBy.empty());
62 void MSXDevice::staticInit()
64 static bool alreadyInit =
false;
65 if (alreadyInit)
return;
81 for (
const auto* dev : referencedBy) {
82 if (!
contains(removed, dev, [](
const auto& d) {
return d.get(); })) {
91 void MSXDevice::lockDevices()
100 auto name = c->getAttributeValue(
"idref");
104 "Unsatisfied dependency: '",
getName(),
105 "' depends on unavailable device '",
108 references.push_back(dev);
109 dev->referencedBy.push_back(
this);
113 void MSXDevice::unlockDevices()
115 for (
auto& r : references) {
163 void MSXDevice::registerSlots()
165 MemRegions tmpMemRegions;
169 unsigned base = m->getAttributeValueAsInt(
"base", 0);
170 unsigned size = m->getAttributeValueAsInt(
"size", 0);
171 if ((base >= 0x10000) || (
size > 0x10000) || ((base +
size) > 0x10000)) {
173 "Invalid memory specification for device ",
174 getName(),
" should be in range "
175 "[0x0000,0x10000).");
177 if (((base & (align - 1)) || (
size & (align - 1))) &&
180 "invalid memory specification for device ",
181 getName(),
" should be aligned on at least 0x",
182 hex_string<4>(align),
'.');
184 tmpMemRegions.emplace_back(BaseSize{base,
size});
186 if (tmpMemRegions.empty()) {
195 ps = slotManager.getSlotNum(primaryConfig->getAttributeValue(
"slot"));
197 throw MSXException(
"Invalid memory specification");
199 if (secondaryConfig) {
200 auto ss_str = secondaryConfig->getAttributeValue(
"slot");
201 ss = slotManager.getSlotNum(ss_str);
202 if ((-16 <= ss) && (ss <= -1) && (ss != ps)) {
204 "Invalid secondary slot specification: \"",
218 if (
auto** primSlotPtr = mutableConfig.findAttributePointer(
"primary_slot")) {
219 ps = slotManager.getSlotNum((*primSlotPtr)->getValue());
220 mutableConfig.removeAttribute(primSlotPtr);
221 if (
auto** secSlotPtr = mutableConfig.findAttributePointer(
"secondary_slot")) {
222 ss = slotManager.getSlotNum((*secSlotPtr)->getValue());
223 mutableConfig.removeAttribute(secSlotPtr);
228 if ((-128 <= ss) && (ss < 0)) {
229 if ((0 <= ps) && (ps < 4) &&
239 slotManager.getAnyFreeSlot(ps, ss);
242 slotManager.getSpecificSlot(-ps - 1, ps, ss);
246 assert((0 <= ps) && (ps <= 3));
258 assert(primaryConfig);
261 if (secondaryConfig) {
262 doc.setAttribute(*secondaryConfig,
"slot", doc.allocateString(
263 (ss == -1) ? std::string_view(
"X") :
tmpStrCat(ss)));
267 "Missing <secondary> tag for device",
getName());
271 int logicalSS = (ss == -1) ? 0 : ss;
272 for (
auto& r : tmpMemRegions) {
274 *
this, ps, logicalSS, r.base, r.size);
275 memRegions.push_back(r);
286 void MSXDevice::unregisterSlots()
288 if (memRegions.empty())
return;
290 int logicalSS = (ss == -1) ? 0 : ss;
291 for (
const auto& [base,
size] : memRegions) {
293 *
this, ps, logicalSS, base,
size);
305 if (memRegions.empty()) {
311 auto lowest =
min_value(memRegions, &BaseSize::base);
313 assert(lowest <= highest);
315 size = highest - lowest;
318 void MSXDevice::registerPorts()
322 unsigned base = i->getAttributeValueAsInt(
"base", 0);
323 unsigned num = i->getAttributeValueAsInt(
"num", 0);
324 auto type = i->getAttributeValue(
"type",
"IO");
325 if (((base + num) > 256) || (num == 0) ||
326 (type !=
one_of(
"I",
"O",
"IO"))) {
345 void MSXDevice::unregisterPorts()
442 return cache[offset];
468 template<
typename Action,
typename... Args>
469 void MSXDevice::clip(
unsigned start,
unsigned size, Action action, Args... args)
471 int ss2 = (ss != -1) ? ss : 0;
473 for (
auto [base, fullBsize] : memRegions) {
475 while (fullBsize > 0) {
476 unsigned bsize =
std::min(fullBsize, ((base + 0x4000) & ~0x3fff) - base);
478 unsigned baseEnd = base + bsize;
480 unsigned clipStart =
std::max(start, base);
482 if (clipStart < clipEnd) {
483 unsigned clipSize = clipEnd - clipStart;
484 action(clipStart, clipSize, args..., ps, ss2);
526 template<
typename Archive>
void setPosN(size_t pos, size_t n)
Starting from position 'pos', set the 'n' following bits to '1'.
void foreachSetBit(Operation op) const
Execute the given operation 'op' for all '1' bits.
void freeSlot(int ps, int ss, const HardwareConfig &hwConfig)
XMLElement * getSecondary() const
XMLDocument & getXMLDocument()
XMLElement * getPrimary() const
MSXMotherBoard & getMotherBoard() const
void register_IO_Out(byte port, MSXDevice *device)
Devices can register their Out ports.
void invalidateRWCache(word start, unsigned size, int ps, int ss)
void register_IO_In(byte port, MSXDevice *device)
Devices can register their In ports.
void fillWCache(unsigned start, unsigned size, byte *wData, int ps, int ss)
void unregister_IO_In(byte port, MSXDevice *device)
void invalidateRCache(word start, unsigned size, int ps, int ss)
void fillRWCache(unsigned start, unsigned size, const byte *rData, byte *wData, int ps, int ss)
void registerMemDevice(MSXDevice &device, int ps, int ss, int base, int size)
Devices can register themself in the MSX slotstructure.
void invalidateWCache(word start, unsigned size, int ps, int ss)
void unregisterMemDevice(MSXDevice &device, int ps, int ss, int base, int size)
void unregister_IO_Out(byte port, MSXDevice *device)
void fillRCache(unsigned start, unsigned size, const byte *rData, int ps, int ss)
bool isExpanded(int ps) const
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
MSXMotherBoard & getMotherBoard() const
Get the mother board this device belongs to.
void invalidateDeviceRCache()
void fillDeviceWCache(unsigned start, unsigned size, byte *wData)
PluggingController & getPluggingController() const
virtual void powerUp(EmuTime::param time)
This method is called when MSX is powered up.
const DeviceConfig & getDeviceConfig2() const
void fillDeviceRWCache(unsigned start, unsigned size, byte *rwData)
Calls MSXCPUInterface::fillXXCache() for the specific (part of) the slot that this device is located ...
CliComm & getCliComm() const
virtual const byte * getReadCacheLine(word start) const
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
void invalidateDeviceWCache()
void getDeviceInfo(TclObject &result) const
Get device info.
virtual void writeIO(word port, byte value, EmuTime::param time)
Write a byte to a given IO port at a certain time to this device.
virtual byte readIRQVector()
Gets IRQ vector used in IM2.
virtual void globalWrite(word address, byte value, EmuTime::param time)
Global writes.
Reactor & getReactor() const
virtual bool allowUnaligned() const
By default we don't allow unaligned <mem> specifications in the config file.
virtual unsigned getBaseSizeAlignment() const
The 'base' and 'size' attribute values need to be at least aligned to CacheLine::SIZE.
MSXDevice(const MSXDevice &)=delete
const XMLElement & getDeviceConfig() const
Get the configuration section for this device.
std::vector< MSXDevice * > Devices
virtual byte readMem(word address, EmuTime::param time)
Read a byte from a location at a certain time from this device.
virtual void getExtraDeviceInfo(TclObject &result) const
void getVisibleMemRegion(unsigned &base, unsigned &size) const
Returns the range where this device is visible in memory.
virtual void writeMem(word address, byte value, EmuTime::param time)
Write a given byte to a given location at a certain time to this device.
virtual byte peekIO(word port, EmuTime::param time) const
Read a byte from a given IO port.
virtual byte peekMem(word address, EmuTime::param time) const
Read a byte from a given memory location.
const HardwareConfig & getHardwareConfig() const
Returns the hardwareconfig this device belongs to.
virtual const std::string & getName() const
Returns a human-readable name for this device.
static byte unmappedRead[0x10000]
LedStatus & getLedStatus() const
void serialize(Archive &ar, unsigned version)
void invalidateDeviceRWCache()
Calls MSXCPUInterface::invalidateXXCache() for the specific (part of) the slot that this device is lo...
Scheduler & getScheduler() const
virtual void getNameList(TclObject &result) const
Returns list of name(s) of this device.
virtual byte * getWriteCacheLine(word start) const
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
void fillDeviceRCache(unsigned start, unsigned size, const byte *rData)
CommandController & getCommandController() const
void testRemove(span< const std::unique_ptr< MSXDevice >> removed) const
Checks whether this device can be removed (no other device has a reference to it).
const Devices & getReferences() const
Get the device references that are specified for this device.
virtual void powerDown(EmuTime::param time)
This method is called when MSX is powered down.
virtual void globalRead(word address, EmuTime::param time)
Global reads.
virtual void reset(EmuTime::param time)
This method is called on reset.
EmuTime::param getCurrentTime() const
MSXCPUInterface & getCPUInterface() const
virtual byte readIO(word port, EmuTime::param time)
Read a byte from an IO port at a certain time from this device.
PluggingController & getPluggingController()
MSXCPUInterface & getCPUInterface()
EmuTime::param getCurrentTime()
Convenience method: This is the same as getScheduler().getCurrentTime().
Scheduler & getScheduler()
CartridgeSlotManager & getSlotManager()
CliComm & getMSXCliComm()
MSXDevice * findDevice(std::string_view name)
Find a MSXDevice by name.
CommandController & getCommandController()
LedStatus & getLedStatus()
Central administration of Connectors and Pluggables.
Contains the main loop of openMSX.
void addListElement(const T &t)
void addDictKeyValue(const Key &key, const Value &value)
void setAttribute(XMLElement &elem, const char *attrName, const char *attrValue)
constexpr bool ispow2(T x) noexcept
Is the given number an integral power of two? That is, does it have exactly one 1-bit in binary repre...
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
This file implemented 3 utility functions:
uint16_t word
16 bit unsigned integer
size_t size(std::string_view utf8)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
auto min_value(InputIterator first, InputIterator last, Proj proj={})
auto max_value(InputIterator first, InputIterator last, Proj proj={})
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
auto rfind_unguarded(RANGE &range, const VAL &val, Proj proj={})
Similar to the find(_if)_unguarded functions above, but searches from the back to front.
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
TemporaryString tmpStrCat(Ts &&... ts)
std::string strCat(Ts &&...ts)
void strAppend(std::string &result, Ts &&...ts)
constexpr auto end(const zstring_view &x)