45static std::optional<ReadOnlySetting> breakedSetting;
46static unsigned breakedSettingCount = 0;
50static constexpr byte SECONDARY_SLOT_BIT = 0x01;
51static constexpr byte MEMORY_WATCH_BIT = 0x02;
52static constexpr byte GLOBAL_RW_BIT = 0x04;
56 return os <<
"CacheLineCounters";
70 "InvalidateReadWrite",
77 return os << names[size_t(evn.
e)];
81 : memoryDebug (motherBoard_)
82 , slottedMemoryDebug(motherBoard_)
83 , ioDebug (motherBoard_)
84 , slotInfo(motherBoard_.getMachineInfoCommand())
85 , subSlottedInfo(motherBoard_.getMachineInfoCommand())
86 , externalSlotInfo(motherBoard_.getMachineInfoCommand())
87 , inputPortInfo (motherBoard_.getMachineInfoCommand())
88 , outputPortInfo(motherBoard_.getMachineInfoCommand())
90 *motherBoard_.getMachineConfig()))
91 , msxcpu(motherBoard_.getCPU())
92 , cliComm(motherBoard_.getMSXCliComm())
93 , motherBoard(motherBoard_)
94 , pauseSetting(motherBoard.getReactor().getGlobalSettings().getPauseSetting())
103 for (
auto& sub1 : slotLayout) {
104 for (
auto& sub2 : sub1) {
122 for (
auto port :
xrange(0x98, 0x9c)) {
123 assert(IO_In [port] == dummyDevice.get());
124 assert(IO_Out[port] == dummyDevice.get());
125 IO_In [port] = delayDevice.get();
126 IO_Out[port] = delayDevice.get();
130 if (breakedSettingCount++ == 0) {
131 assert(!breakedSetting);
132 breakedSetting.emplace(
134 "breaked",
"Similar to 'debug breaked'",
142 if (--breakedSettingCount == 0) {
143 assert(breakedSetting);
144 breakedSetting.reset();
147 removeAllWatchPoints();
150 for (
auto port :
xrange(0x98, 0x9c)) {
151 assert(IO_In [port] == delayDevice.get());
152 assert(IO_Out[port] == delayDevice.get());
153 IO_In [port] = dummyDevice.get();
154 IO_Out[port] = dummyDevice.get();
161 for (
auto port :
xrange(256)) {
162 if (IO_In[port] != dummyDevice.get()) {
163 std::cout <<
"In-port " << port <<
" still registered "
164 << IO_In[port]->getName() <<
'\n';
167 if (IO_Out[port] != dummyDevice.get()) {
168 std::cout <<
"Out-port " << port <<
" still registered "
169 << IO_Out[port]->getName() <<
'\n';
173 for (
auto primSlot :
xrange(4)) {
175 for (
auto secSlot :
xrange(4)) {
176 for (
auto page :
xrange(4)) {
177 assert(slotLayout[primSlot][secSlot][page] == dummyDevice.get());
184void MSXCPUInterface::removeAllWatchPoints()
186 while (!watchPoints.empty()) {
191byte MSXCPUInterface::readMemSlow(
word address, EmuTime::param time)
197 for (
auto&
g : globalReads) {
200 if (
g.addr == address) [[unlikely]] {
201 g.device->globalRead(address, time);
210 if ((address == 0xFFFF) &&
isExpanded(primarySlotState[3])) [[unlikely]] {
211 return 0xFF ^ subSlotRegister[primarySlotState[3]];
213 return visibleDevices[address >> 14]->readMem(address, time);
217void MSXCPUInterface::writeMemSlow(
word address,
byte value, EmuTime::param time)
220 if ((address == 0xFFFF) &&
isExpanded(primarySlotState[3])) [[unlikely]] {
221 setSubSlot(primarySlotState[3], value);
226 visibleDevices[address>>14]->writeMem(address, value, time);
231 for (
auto&
g : globalWrites) {
234 if (
g.addr == address) [[unlikely]] {
235 g.device->globalWrite(address, value, time);
254 if (expanded[ps] == 0) {
255 for (
auto page :
xrange(4)) {
256 if (slotLayout[ps][0][page] != dummyDevice.get()) {
258 "it's already in use.");
268 std::span<
const std::unique_ptr<MSXDevice>> allowed)
const
271 if (expanded[ps] != 1)
return;
273 std::vector<const MSXDevice*> inUse;
275 auto isAllowed = [&](
const MSXDevice* dev) {
276 return (dev == dummyDevice.get()) ||
277 contains(allowed, dev, [](
const auto& d) {
return d.get(); });
280 if (!isAllowed(dev)) {
282 inUse.push_back(dev);
287 for (
auto ss :
xrange(4)) {
288 for (
auto page :
xrange(4)) {
289 const MSXDevice* device = slotLayout[ps][ss][page];
291 for (
const auto* dev : memDev->getDevices()) {
300 if (inUse.empty())
return;
302 auto msg =
strCat(
"Can't remove slot expander from slot ", ps,
303 " because the following devices are still inserted:");
304 for (
const auto& d : inUse) {
315 std::span<const std::unique_ptr<MSXDevice>> dummy;
328 disallowReadCache [0xFF] |= SECONDARY_SLOT_BIT;
329 disallowWriteCache[0xFF] |= SECONDARY_SLOT_BIT;
331 disallowReadCache [0xFF] &= ~SECONDARY_SLOT_BIT;
332 disallowWriteCache[0xFF] &= ~SECONDARY_SLOT_BIT;
337MSXDevice*& MSXCPUInterface::getDevicePtr(
byte port,
bool isIn)
339 MSXDevice** devicePtr = isIn ? &IO_In[port] : &IO_Out[port];
341 devicePtr = &watch->getDevicePtr();
343 if (*devicePtr == delayDevice.get()) {
344 devicePtr = isIn ? &delayDevice->getInDevicePtr (port)
345 : &delayDevice->getOutDevicePtr(port);
352 MSXDevice*& devicePtr = getDevicePtr(port,
true);
353 register_IO(port,
true, devicePtr, device);
358 MSXDevice*& devicePtr = getDevicePtr(port,
true);
359 unregister_IO(devicePtr, device);
364 MSXDevice*& devicePtr = getDevicePtr(port,
false);
365 register_IO(port,
false, devicePtr, device);
370 MSXDevice*& devicePtr = getDevicePtr(port,
false);
371 unregister_IO(devicePtr, device);
409void MSXCPUInterface::register_IO(
int port,
bool isIn,
412 if (devicePtr == dummyDevice.get()) {
416 if (
auto* multi =
dynamic_cast<MSXMultiIODevice*
>(devicePtr)) {
418 multi->addDevice(device);
422 multi->addDevice(devicePtr);
423 multi->addDevice(device);
428 if (devices.getAttributeValueAsBool(
"overlap_warning",
true)) {
430 "Conflicting input port 0x",
432 " for devices ", devicePtr->
getName());
438void MSXCPUInterface::unregister_IO(MSXDevice*& devicePtr, MSXDevice* device)
440 if (
auto* multi =
dynamic_cast<MSXMultiIODevice*
>(devicePtr)) {
442 multi->removeDevice(device);
443 auto& devices = multi->getDevices();
444 if (devices.size() == 1) {
446 devicePtr = devices.front();
452 assert(devicePtr == device);
453 devicePtr = dummyDevice.get();
460 MSXDevice*& devicePtr = getDevicePtr(port,
true);
461 if (devicePtr != oldDevice) {
465 devicePtr = newDevice;
471 MSXDevice*& devicePtr = getDevicePtr(port,
false);
472 if (devicePtr != oldDevice) {
476 devicePtr = newDevice;
480[[noreturn]]
static void reportMemOverlap(
int ps,
int ss,
const MSXDevice& dev1,
const MSXDevice& dev2)
483 "Overlapping memory devices in slot ", ps,
'.', ss,
487void MSXCPUInterface::testRegisterSlot(
488 const MSXDevice& device,
int ps,
int ss,
unsigned base,
unsigned size)
490 auto page = base >> 14;
491 MSXDevice*& slot = slotLayout[ps][ss][page];
492 if (size == 0x4000) {
494 if (slot != dummyDevice.get()) {
495 reportMemOverlap(ps, ss, *slot, device);
499 if (slot == dummyDevice.get()) {
501 }
else if (
auto* multi =
dynamic_cast<MSXMultiMemDevice*
>(slot)) {
503 if (!multi->canAdd(base, size)) {
504 reportMemOverlap(ps, ss, *slot, device);
508 reportMemOverlap(ps, ss, *slot, device);
513void MSXCPUInterface::registerSlot(
514 MSXDevice& device,
int ps,
int ss,
unsigned base,
unsigned size)
516 auto page = narrow<byte>(base >> 14);
517 MSXDevice*& slot = slotLayout[ps][ss][page];
518 if (size == 0x4000) {
520 assert(slot == dummyDevice.get());
524 if (slot == dummyDevice.get()) {
526 auto* multi =
new MSXMultiMemDevice(device.getHardwareConfig());
527 multi->add(device, base, size);
529 }
else if (
auto* multi =
dynamic_cast<MSXMultiMemDevice*
>(slot)) {
531 assert(multi->canAdd(base, size));
532 multi->add(device, base, size);
542void MSXCPUInterface::unregisterSlot(
543 MSXDevice& device,
int ps,
int ss,
unsigned base,
unsigned size)
545 auto page = narrow<byte>(base >> 14);
546 MSXDevice*& slot = slotLayout[ps][ss][page];
547 if (
auto* multi =
dynamic_cast<MSXMultiMemDevice*
>(slot)) {
549 multi->remove(device, base, size);
550 if (multi->empty()) {
552 slot = dummyDevice.get();
556 assert(slot == &device);
557 slot = dummyDevice.get();
564 MSXDevice& device,
int ps,
int ss,
unsigned base_,
unsigned size_)
568 "Slot ", ps,
'.', ss,
569 " does not exist because slot is not expanded.");
577 auto partialSize = std::min(size, ((base + 0x4000) & ~0x3FFF) - base);
578 testRegisterSlot(device, ps, ss, base, partialSize);
586 auto partialSize = std::min(size, ((base + 0x4000) & ~0x3FFF) - base);
587 registerSlot(device, ps, ss, base, partialSize);
594 MSXDevice& device,
int ps,
int ss,
unsigned base,
unsigned size)
598 auto partialSize = std::min(size, ((base + 0x4000) & ~0x3FFF) - base);
599 unregisterSlot(device, ps, ss, base, partialSize);
607 globalWrites.push_back({&device, address});
615 GlobalRwInfo info = { &device, address };
618 for (
const auto&
g : globalWrites) {
631 globalReads.push_back({&device, address});
639 GlobalRwInfo info = { &device, address };
642 for (
const auto&
g : globalReads) {
653ALWAYS_INLINE void MSXCPUInterface::updateVisible(
byte page,
byte ps,
byte ss)
655 MSXDevice* newDevice = slotLayout[ps][ss][page];
656 if (visibleDevices[page] != newDevice) {
657 visibleDevices[page] = newDevice;
661void MSXCPUInterface::updateVisible(
byte page)
663 updateVisible(page, primarySlotState[page], secondarySlotState[page]);
669 msxcpu.
invalidateRWCache(start, size, ps, ss, disallowReadCache, disallowWriteCache);
674 msxcpu.
invalidateRCache(start, size, ps, ss, disallowReadCache, disallowWriteCache);
679 msxcpu.
invalidateWCache(start, size, ps, ss, disallowReadCache, disallowWriteCache);
685 msxcpu.
fillRWCache(start, size, rData, wData, ps, ss, disallowReadCache, disallowWriteCache);
690 msxcpu.
fillRCache(start, size, rData, ps, ss, disallowReadCache, disallowWriteCache);
695 msxcpu.
fillWCache(start, size, wData, ps, ss, disallowReadCache, disallowWriteCache);
700 for (
auto i :
xrange(
byte(4))) {
725 if (
byte ps0 = (value >> 0) & 3; primarySlotState[0] != ps0) [[unlikely]] {
726 primarySlotState[0] = ps0;
727 byte ss0 = (subSlotRegister[ps0] >> 0) & 3;
728 secondarySlotState[0] = ss0;
729 updateVisible(0, ps0, ss0);
731 if (
byte ps1 = (value >> 2) & 3; primarySlotState[1] != ps1) [[unlikely]] {
732 primarySlotState[1] = ps1;
733 byte ss1 = (subSlotRegister[ps1] >> 2) & 3;
734 secondarySlotState[1] = ss1;
735 updateVisible(1, ps1, ss1);
737 if (
byte ps2 = (value >> 4) & 3; primarySlotState[2] != ps2) [[unlikely]] {
738 primarySlotState[2] = ps2;
739 byte ss2 = (subSlotRegister[ps2] >> 4) & 3;
740 secondarySlotState[2] = ss2;
741 updateVisible(2, ps2, ss2);
743 if (
byte ps3 = (value >> 6) & 3; primarySlotState[3] != ps3) [[unlikely]] {
744 bool oldExpanded =
isExpanded(primarySlotState[3]);
746 primarySlotState[3] = ps3;
747 byte ss3 = (subSlotRegister[ps3] >> 6) & 3;
748 secondarySlotState[3] = ss3;
749 updateVisible(3, ps3, ss3);
750 if (oldExpanded != newExpanded) [[unlikely]] {
756void MSXCPUInterface::setSubSlot(
byte primSlot,
byte value)
758 subSlotRegister[primSlot] = value;
759 for (
byte page = 0; page < 4; ++page, value >>= 2) {
760 if (primSlot == primarySlotState[page]) {
761 secondarySlotState[page] = value & 3;
770 if ((address == 0xFFFF) &&
isExpanded(primarySlotState[3])) {
771 return 0xFF ^ subSlotRegister[primarySlotState[3]];
773 return visibleDevices[address >> 14]->peekMem(address, time);
779 byte primSlot = (address & 0xC0000) >> 18;
780 byte subSlot = (address & 0x30000) >> 16;
781 byte page = (address & 0x0C000) >> 14;
782 word offset = (address & 0xFFFF);
787 if ((offset == 0xFFFF) &&
isExpanded(primSlot)) {
788 return 0xFF ^ subSlotRegister[primSlot];
790 return slotLayout[primSlot][subSlot][page]->peekMem(offset, time);
796 byte primSlot = (address & 0xC0000) >> 18;
797 byte subSlot = (address & 0x30000) >> 16;
798 byte page = (address & 0x0C000) >> 14;
799 word offset = (address & 0xFFFF);
804 if ((offset == 0xFFFF) &&
isExpanded(primSlot)) {
805 return 0xFF ^ subSlotRegister[primSlot];
807 return slotLayout[primSlot][subSlot][page]->peekMem(offset, time);
814 byte primSlot = (address & 0xC0000) >> 18;
815 byte subSlot = (address & 0x30000) >> 16;
816 byte page = (address & 0x0C000) >> 14;
817 word offset = (address & 0xFFFF);
822 if ((offset == 0xFFFF) &&
isExpanded(primSlot)) {
823 setSubSlot(primSlot, value);
825 slotLayout[primSlot][subSlot][page]->writeMem(offset, value, time);
832 breakPoints.push_back(std::move(bp));
844 it != breakPoints.end()) {
846 breakPoints.erase(it);
854 std::vector<BreakPoint> bpCopy;
855 for (
const auto& bp : breakPoints) {
856 if (bp.isEnabled() && bp.getAddress() == pc) bpCopy.push_back(bp);
858 std::vector<DebugCondition> condCopy;
859 for (
const auto& cond : conditions) {
860 if (cond.isEnabled()) condCopy.push_back(cond);
862 if (bpCopy.empty() && condCopy.empty())
return false;
867 for (
auto& p : bpCopy) {
868 bool remove = p.checkAndExecute(globalCliComm, interp);
873 for (
auto& c : condCopy) {
874 bool remove = c.checkAndExecute(globalCliComm, interp);
882void MSXCPUInterface::registerWatchPoint(
WatchPoint& wp)
895 updateMemWatch(type);
902void MSXCPUInterface::unregisterWatchPoint(WatchPoint& wp)
904 auto type = wp.getType();
908 wp.unregisterIOWatch(IO_In);
911 wp.unregisterIOWatch(IO_Out);
915 updateMemWatch(type);
925 watchPoints.push_back(watchPoint);
926 registerWatchPoint(*watchPoint);
935 it !=
end(watchPoints)) {
938 watchPoints.erase(it);
939 unregisterWatchPoint(*watchPoint);
946 it != watchPoints.end()) {
954 conditions.push_back(std::move(cond));
961 [](
auto& e) {
return &e; }));
968 it != conditions.end()) {
970 conditions.erase(it);
976 std::span<std::bitset<CacheLine::SIZE>,
CacheLine::NUM> watchSet =
978 for (
auto i :
xrange(CacheLine::NUM)) {
981 for (
const auto& w : watchPoints) {
982 if (w->getType() == type) {
983 auto begin = w->getBeginAddress();
984 auto end = w->getEndAddress();
987 for (
unsigned addr = *
begin; addr <= *
end; ++addr) {
994 if (readWatchSet [i].any()) {
995 disallowReadCache [i] |= MEMORY_WATCH_BIT;
997 disallowReadCache [i] &= ~MEMORY_WATCH_BIT;
999 if (writeWatchSet[i].any()) {
1000 disallowWriteCache[i] |= MEMORY_WATCH_BIT;
1002 disallowWriteCache[i] &= ~MEMORY_WATCH_BIT;
1009 unsigned address,
unsigned value)
1011 assert(!watchPoints.empty());
1017 TclObject(
int(address)));
1019 interp.setVariable(TclObject(
"wp_last_value"),
1020 TclObject(
int(value)));
1024 for(
auto wpCopy = watchPoints;
auto& w : wpCopy) {
1025 if ((w->getBeginAddress() <= address) &&
1026 (w->getEndAddress() >= address) &&
1027 (w->getType() == type)) {
1028 bool remove = w->checkAndExecute(globalCliComm, interp);
1035 interp.unsetVariable(
"wp_last_address");
1036 interp.unsetVariable(
"wp_last_value");
1043 if (breaked)
return;
1049 breakedSetting->setReadOnlyValue(
TclObject(
"true"));
1071 breakedSetting->setReadOnlyValue(
TclObject(
"false"));
1085 breakPoints.clear();
1091 assert(0 <= ps && ps < 4);
1092 assert(0 <= ss && ss < 4);
1093 assert(0 <= page && page < 4);
1094 return slotLayout[ps][ss][page];
1099MSXCPUInterface::MemoryDebug::MemoryDebug(
MSXMotherBoard& motherBoard_)
1101 "The memory currently visible for the CPU.", 0x10000)
1105byte MSXCPUInterface::MemoryDebug::read(
unsigned address, EmuTime::param time)
1107 const auto&
interface =
OUTER(MSXCPUInterface, memoryDebug);
1108 return interface.peekMem(narrow<word>(address), time);
1111void MSXCPUInterface::MemoryDebug::write(
unsigned address,
byte value,
1112 EmuTime::param time)
1115 return interface.writeMem(narrow<word>(address), value, time);
1121MSXCPUInterface::SlottedMemoryDebug::SlottedMemoryDebug(
1122 MSXMotherBoard& motherBoard_)
1123 : SimpleDebuggable(motherBoard_,
"slotted memory",
1124 "The memory in slots and subslots.", 0x10000 * 4 * 4)
1128byte MSXCPUInterface::SlottedMemoryDebug::read(
unsigned address, EmuTime::param time)
1131 return interface.peekSlottedMem(address, time);
1134void MSXCPUInterface::SlottedMemoryDebug::write(
unsigned address,
byte value,
1135 EmuTime::param time)
1138 return interface.writeSlottedMem(address, value, time);
1144static unsigned getSlot(
1145 Interpreter& interp,
const TclObject& token,
const std::string& itemName)
1147 unsigned slot = token.getInt(interp);
1149 throw CommandException(itemName,
" must be in range 0..3");
1154MSXCPUInterface::SlotInfo::SlotInfo(
1155 InfoCommand& machineInfoCommand)
1156 : InfoTopic(machineInfoCommand,
"slot")
1160void MSXCPUInterface::SlotInfo::execute(std::span<const TclObject> tokens,
1161 TclObject& result)
const
1163 checkNumArgs(tokens, 5, Prefix{2},
"primary secondary page");
1164 auto& interp = getInterpreter();
1165 unsigned ps = getSlot(interp, tokens[2],
"Primary slot");
1166 unsigned ss = getSlot(interp, tokens[3],
"Secondary slot");
1167 unsigned page = getSlot(interp, tokens[4],
"Page");
1169 if (!interface.isExpanded(narrow<int>(ps))) {
1172 interface.slotLayout[ps][ss][page]->getNameList(result);
1175std::string MSXCPUInterface::SlotInfo::help(std::span<const TclObject> )
const
1177 return "Retrieve name of the device inserted in given "
1178 "primary slot / secondary slot / page.";
1184MSXCPUInterface::SubSlottedInfo::SubSlottedInfo(
1185 InfoCommand& machineInfoCommand)
1186 : InfoTopic(machineInfoCommand,
"issubslotted")
1190void MSXCPUInterface::SubSlottedInfo::execute(std::span<const TclObject> tokens,
1191 TclObject& result)
const
1193 checkNumArgs(tokens, 3,
"primary");
1195 result = interface.isExpanded(narrow<int>(
1196 getSlot(getInterpreter(), tokens[2],
"Slot")));
1199std::string MSXCPUInterface::SubSlottedInfo::help(
1200 std::span<const TclObject> )
const
1202 return "Indicates whether a certain primary slot is expanded.";
1208MSXCPUInterface::ExternalSlotInfo::ExternalSlotInfo(
1209 InfoCommand& machineInfoCommand)
1210 : InfoTopic(machineInfoCommand,
"isexternalslot")
1214void MSXCPUInterface::ExternalSlotInfo::execute(
1215 std::span<const TclObject> tokens, TclObject& result)
const
1217 checkNumArgs(tokens, Between{3, 4},
"primary ?secondary?");
1220 auto& interp = getInterpreter();
1221 switch (tokens.size()) {
1223 ss = narrow<int>(getSlot(interp, tokens[3],
"Secondary slot"));
1226 ps = narrow<int>(getSlot(interp, tokens[2],
"Primary slot"));
1230 const auto& manager = interface.motherBoard.getSlotManager();
1231 result = manager.isExternalSlot(ps, ss,
true);
1234std::string MSXCPUInterface::ExternalSlotInfo::help(
1235 std::span<const TclObject> )
const
1237 return "Indicates whether a certain slot is external or internal.";
1243MSXCPUInterface::IODebug::IODebug(MSXMotherBoard& motherBoard_)
1244 : SimpleDebuggable(motherBoard_,
"ioports",
"IO ports.", 0x100)
1248byte MSXCPUInterface::IODebug::read(
unsigned address, EmuTime::param time)
1251 return interface.IO_In[address & 0xFF]->peekIO(narrow<word>(address), time);
1254void MSXCPUInterface::IODebug::write(
unsigned address,
byte value, EmuTime::param time)
1257 interface.writeIO(
word(address), value, time);
1263MSXCPUInterface::IOInfo::IOInfo(InfoCommand& machineInfoCommand,
const char* name_)
1264 : InfoTopic(machineInfoCommand, name_)
1268void MSXCPUInterface::IOInfo::helper(
1269 std::span<const TclObject> tokens, TclObject& result, std::span<MSXDevice*, 256> devices)
const
1271 checkNumArgs(tokens, 3,
"port");
1272 unsigned port = tokens[2].getInt(getInterpreter());
1274 throw CommandException(
"Port must be in range 0..255");
1276 devices[port]->getNameList(result);
1278void MSXCPUInterface::IInfo::execute(
1279 std::span<const TclObject> tokens, TclObject& result)
const
1282 helper(tokens, result, interface.IO_In);
1284void MSXCPUInterface::OInfo::execute(
1285 std::span<const TclObject> tokens, TclObject& result)
const
1288 helper(tokens, result, interface.IO_Out);
1291std::string MSXCPUInterface::IOInfo::help(std::span<const TclObject> )
const
1293 return "Return the name of the device connected to the given IO port.";
1297template<
typename Archive>
1304 if constexpr (!Archive::IS_LOADER) {
1305 for (
auto i :
xrange(4)) {
1306 prim |=
byte(primarySlotState[i] << (2 * i));
1309 ar.serialize(
"primarySlots", prim,
1310 "subSlotRegs", subSlotRegister);
1311 if constexpr (Archive::IS_LOADER) {
1313 for (
auto i :
xrange(
byte(4))) {
1314 setSubSlot(i, subSlotRegister[i]);
1319 ar.serialize(
"vdpDelay", *delayDevice);
void tick(CacheLineCounters e) const
void setOnce(Interpreter &interp, const TclObject &o)
std::string getIdStr() const
virtual void update(UpdateType type, std::string_view name, std::string_view value)=0
void printWarning(std::string_view message)
General debugger condition Like breakpoints, but not tied to a specific address.
static std::unique_ptr< VDPIODelay > createVDPIODelay(const HardwareConfig &hwConf, MSXCPUInterface &cpuInterface)
static constexpr EmuDuration epsilon()
void distributeEvent(Event &&event)
Schedule the given event for delivery.
byte parseSlotMap() const
Parses a slot mapping.
const XMLElement & getDevicesElem() const
void setVariable(const TclObject &name, const TclObject &value)
void register_IO_Out(byte port, MSXDevice *device)
Devices can register their Out ports.
void unregister_IO_In_range(byte port, unsigned num, MSXDevice *device)
void setWatchPoint(const std::shared_ptr< WatchPoint > &watchPoint)
void invalidateRWCache(word start, unsigned size, int ps, int ss)
MSXCPUInterface(MSXMotherBoard &motherBoard)
void insertBreakPoint(BreakPoint bp)
void unregister_IO_Out_range(byte port, unsigned num, MSXDevice *device)
void register_IO_In(byte port, MSXDevice *device)
Devices can register their In ports.
MSXDevice * getMSXDevice(int ps, int ss, int page)
void fillWCache(unsigned start, unsigned size, byte *wData, int ps, int ss)
void unregister_IO_In(byte port, MSXDevice *device)
bool replace_IO_Out(byte port, MSXDevice *oldDevice, MSXDevice *newDevice)
void changeExpanded(bool newExpanded)
void unregister_IO_InOut_range(byte port, unsigned num, MSXDevice *device)
void unregisterMemDevice(MSXDevice &device, int ps, int ss, unsigned base, unsigned size)
void register_IO_In_range(byte port, unsigned num, MSXDevice *device)
void removeCondition(const DebugCondition &cond)
byte peekMem(word address, EmuTime::param time) const
Peek memory location.
byte readIRQVector() const
CPU uses this method to read 'extra' data from the data bus used in interrupt routines.
void unregister_IO_InOut(byte port, MSXDevice *device)
void testUnsetExpanded(int ps, std::span< const std::unique_ptr< MSXDevice > > allowed) const
void writeSlottedMem(unsigned address, byte value, EmuTime::param time)
void setPrimarySlots(byte value)
void invalidateRCache(word start, unsigned size, int ps, int ss)
void unregisterGlobalWrite(MSXDevice &device, word address)
void unregisterGlobalRead(MSXDevice &device, word address)
byte peekSlottedMem(unsigned address, EmuTime::param time) const
void removeWatchPoint(std::shared_ptr< WatchPoint > watchPoint)
void fillRWCache(unsigned start, unsigned size, const byte *rData, byte *wData, int ps, int ss)
void reset()
Reset (the slot state)
void setCondition(DebugCondition cond)
void invalidateWCache(word start, unsigned size, int ps, int ss)
void unsetExpanded(int ps)
bool isFastForward() const
void register_IO_InOut(byte port, MSXDevice *device)
Convenience methods for {un}register_IO_{In,Out}.
bool checkBreakPoints(unsigned pc)
void serialize(Archive &ar, unsigned version)
void register_IO_Out_range(byte port, unsigned num, MSXDevice *device)
void registerGlobalRead(MSXDevice &device, word address)
(Un)register global read.
byte readSlottedMem(unsigned address, EmuTime::param time)
void registerMemDevice(MSXDevice &device, int ps, int ss, unsigned base, unsigned size)
Devices can register themself in the MSX slot structure.
void removeBreakPoint(const BreakPoint &bp)
void unregister_IO_Out(byte port, MSXDevice *device)
void registerGlobalWrite(MSXDevice &device, word address)
(Un)register global writes.
bool replace_IO_In(byte port, MSXDevice *oldDevice, MSXDevice *newDevice)
These methods replace a previously registered device with a new one.
void fillRCache(unsigned start, unsigned size, const byte *rData, int ps, int ss)
bool isExpanded(int ps) const
void register_IO_InOut_range(byte port, unsigned num, MSXDevice *device)
void invalidateAllSlotsRWCache(word start, unsigned size)
Invalidate the CPU its cache for the interval [start, start + size) For example MSXMemoryMapper and M...
void fillWCache(unsigned start, unsigned size, byte *wData, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
void updateVisiblePage(byte page, byte primarySlot, byte secondarySlot)
Inform CPU of bank switch.
void fillRCache(unsigned start, unsigned size, const byte *rData, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
void fillRWCache(unsigned start, unsigned size, const byte *rData, byte *wData, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
Fill the read and write cache lines for a specific slot with the specified value.
void invalidateRCache(unsigned start, unsigned size, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
void exitCPULoopSync()
See CPUCore::exitCPULoopSync()
void invalidateRWCache(unsigned start, unsigned size, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
Similar to the method above, but only invalidates one specific slot.
void setInterface(MSXCPUInterface *interface)
void invalidateWCache(unsigned start, unsigned size, int ps, int ss, std::span< const byte, 256 > disallowRead, std::span< const byte, 256 > disallowWrite)
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
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.
const HardwareConfig * getMachineConfig() const
Scheduler & getScheduler()
StateChangeDistributor & getStateChangeDistributor()
byte readIRQVector() const
Contains the main loop of openMSX.
CommandController & getCommandController()
GlobalCliComm & getGlobalCliComm()
Interpreter & getInterpreter()
EventDistributor & getEventDistributor()
void schedule(EmuTime::param limit)
Schedule till a certain moment in time.
auto tempBlockNewEventsDuringReplay()
void registerIOWatch(MSXMotherBoard &motherBoard, std::span< MSXDevice *, 256 > devices)
This file implemented 3 utility functions:
uint8_t byte
8 bit unsigned integer
std::ostream & operator<<(std::ostream &os, EnumTypeName< CacheLineCounters >)
uint16_t word
16 bit unsigned integer
constexpr void fill(ForwardRange &&range, const T &value)
auto remove(ForwardRange &&range, const T &value)
auto find(InputRange &&range, const T &value)
#define OUTER(type, member)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
ITER find_unguarded(ITER first, ITER last, const VAL &val, Proj proj={})
Faster alternative to 'find' when it's guaranteed that the value will be found (if not the behavior i...
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.
void strAppend(std::string &result, Ts &&...ts)
constexpr auto xrange(T e)
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)