22 : deviceConfig(config)
28 : deviceConfig(config)
33void MSXDevice::initName(std::string_view name)
58 assert(referencedBy.empty());
61void MSXDevice::staticInit()
63 static bool alreadyInit =
false;
64 if (alreadyInit)
return;
80 for (
const auto* dev : referencedBy) {
81 if (!
contains(removed, dev, [](
const auto& d) {
return d.get(); })) {
90void MSXDevice::lockDevices()
99 auto name = c->getAttributeValue(
"idref");
103 "Unsatisfied dependency: '",
getName(),
104 "' depends on unavailable device '",
107 references.push_back(dev);
108 dev->referencedBy.push_back(
this);
112void MSXDevice::unlockDevices()
114 for (
auto& r : references) {
162void MSXDevice::registerSlots()
164 MemRegions tmpMemRegions;
166 assert(std::has_single_bit(align));
168 unsigned base = m->getAttributeValueAsInt(
"base", 0);
169 unsigned size = m->getAttributeValueAsInt(
"size", 0);
170 if ((base >= 0x10000) || (size > 0x10000) || ((base + size) > 0x10000)) {
172 "Invalid memory specification for device ",
173 getName(),
" should be in range "
174 "[0x0000,0x10000).");
176 if (((base & (align - 1)) || (size & (align - 1))) &&
179 "invalid memory specification for device ",
180 getName(),
" should be aligned on at least 0x",
181 hex_string<4>(align),
'.');
183 tmpMemRegions.emplace_back(BaseSize{base,
size});
185 if (tmpMemRegions.empty()) {
194 ps = slotManager.getSlotNum(primaryConfig->getAttributeValue(
"slot"));
196 throw MSXException(
"Invalid memory specification");
198 if (secondaryConfig) {
199 auto ss_str = secondaryConfig->getAttributeValue(
"slot");
200 ss = slotManager.getSlotNum(ss_str);
201 if ((-16 <= ss) && (ss <= -1) && (ss != ps)) {
203 "Invalid secondary slot specification: \"",
217 if (
auto** primSlotPtr = mutableConfig.findAttributePointer(
"primary_slot")) {
218 ps = slotManager.getSlotNum((*primSlotPtr)->getValue());
219 mutableConfig.removeAttribute(primSlotPtr);
220 if (
auto** secSlotPtr = mutableConfig.findAttributePointer(
"secondary_slot")) {
221 ss = slotManager.getSlotNum((*secSlotPtr)->getValue());
222 mutableConfig.removeAttribute(secSlotPtr);
227 if ((-128 <= ss) && (ss < 0)) {
228 if ((0 <= ps) && (ps < 4) &&
238 slotManager.getAnyFreeSlot(ps, ss);
241 slotManager.getSpecificSlot(-ps - 1, ps, ss);
245 assert((0 <= ps) && (ps <= 3));
257 assert(primaryConfig);
260 if (secondaryConfig) {
261 doc.setAttribute(*secondaryConfig,
"slot", doc.allocateString(
262 (ss == -1) ? std::string_view(
"X") :
tmpStrCat(ss)));
266 "Missing <secondary> tag for device",
getName());
270 int logicalSS = (ss == -1) ? 0 : ss;
271 for (
const auto& r : tmpMemRegions) {
273 *
this, ps, logicalSS, r.base, r.size);
274 memRegions.push_back(r);
285void MSXDevice::unregisterSlots()
287 if (memRegions.empty())
return;
289 int logicalSS = (ss == -1) ? 0 : ss;
290 for (
const auto& [base, size] : memRegions) {
292 *
this, ps, logicalSS, base, size);
304 if (memRegions.empty()) {
310 auto lowest =
min_value(memRegions, &BaseSize::base);
311 auto highest =
max_value(memRegions, &BaseSize::end);
312 assert(lowest <= highest);
314 size = highest - lowest;
317void MSXDevice::registerPorts()
321 unsigned base = i->getAttributeValueAsInt(
"base", 0);
322 unsigned num = i->getAttributeValueAsInt(
"num", 0);
323 auto type = i->getAttributeValue(
"type",
"IO");
324 if (((base + num) > 256) || (num == 0) ||
325 (type !=
one_of(
"I",
"O",
"IO"))) {
344void MSXDevice::unregisterPorts()
441 return cache[offset];
467template<
typename Action,
typename... Args>
468void MSXDevice::clip(
unsigned start,
unsigned size, Action action, Args... args)
470 assert(start < 0x10000);
471 int ss2 = (ss != -1) ? ss : 0;
472 unsigned end = start + size;
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);
481 unsigned clipEnd = std::min(
end, baseEnd);
482 if (clipStart < clipEnd) {
483 unsigned clipSize = clipEnd - clipStart;
484 action(narrow<word>(clipStart), clipSize, args..., ps, ss2);
526template<
typename Archive>
void setPosN(size_t pos, size_t n)
Starting from position 'pos', set the 'n' following bits to '1'.
void foreachSetBit(std::invocable< size_t > auto op) const
Execute the given operation 'op' for all '1' bits.
void freeSlot(int ps, int ss, const HardwareConfig &hwConfig)
XMLElement * getPrimary() const
XMLDocument & getXMLDocument()
XMLElement * getSecondary() 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 unregisterMemDevice(MSXDevice &device, int ps, int ss, unsigned base, unsigned size)
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 invalidateWCache(word start, unsigned size, int ps, int ss)
void registerMemDevice(MSXDevice &device, int ps, int ss, unsigned base, unsigned size)
Devices can register themself in the MSX slot structure.
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.
static std::array< byte, 0x10000 > unmappedRead
const HardwareConfig & getHardwareConfig() const
Returns the hardwareconfig this device belongs to.
void fillDeviceRWCache(unsigned start, unsigned size, byte *rwData)
Calls MSXCPUInterface::fillXXCache() for the specific (part of) the slot that this device is located ...
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.
const DeviceConfig & getDeviceConfig2() const
virtual unsigned getBaseSizeAlignment() const
The 'base' and 'size' attribute values need to be at least aligned to CacheLine::SIZE.
MSXDevice(const MSXDevice &)=delete
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.
virtual const std::string & getName() const
Returns a human-readable name for this device.
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.
void testRemove(std::span< const std::unique_ptr< MSXDevice > > removed) const
Checks whether this device can be removed (no other device has a reference to it).
virtual byte * getWriteCacheLine(word start)
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
const XMLElement & getDeviceConfig() const
Get the configuration section for this device.
void fillDeviceRCache(unsigned start, unsigned size, const byte *rData)
CommandController & getCommandController() const
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.
MSXCliComm & getCliComm() const
PluggingController & getPluggingController()
EmuTime::param getCurrentTime() const
Convenience method: This is the same as getScheduler().getCurrentTime().
MSXCPUInterface & getCPUInterface()
Scheduler & getScheduler()
MSXDevice * findDevice(std::string_view name)
Find a MSXDevice by name.
CommandController & getCommandController()
MSXCliComm & getMSXCliComm()
LedStatus & getLedStatus()
CartridgeSlotManager & getSlotManager()
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)
This file implemented 3 utility functions:
uint16_t word
16 bit unsigned integer
constexpr void fill(ForwardRange &&range, const T &value)
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)
void strAppend(std::string &result, Ts &&...ts)
constexpr auto end(const zstring_view &x)