openMSX
MSXDeviceSwitch.cc
Go to the documentation of this file.
1 #include "MSXDeviceSwitch.hh"
2 #include "MSXSwitchedDevice.hh"
3 #include "MSXCPUInterface.hh"
4 #include "MSXException.hh"
5 #include "ranges.hh"
6 #include "serialize.hh"
7 #include <cassert>
8 
9 namespace openmsx {
10 
12  : MSXDevice(config)
13 {
14  ranges::fill(devices, nullptr);
15  count = 0;
16  selected = 0;
17 }
18 
20 {
21  // all devices must be unregistered
22  assert(ranges::all_of(devices, [](auto* dev) { return dev == nullptr; }));
23  assert(count == 0);
24 }
25 
27 {
28  if (devices[id]) {
29  // TODO implement multiplexing
30  throw MSXException(
31  "Already have a switched device with id ", int(id));
32  }
33  devices[id] = device;
34  if (count == 0) {
35  for (byte port = 0x40; port < 0x50; ++port) {
36  getCPUInterface().register_IO_In (port, this);
37  getCPUInterface().register_IO_Out(port, this);
38  }
39  }
40  ++count;
41 }
42 
44 {
45  --count;
46  if (count == 0) {
47  for (byte port = 0x40; port < 0x50; ++port) {
48  getCPUInterface().unregister_IO_Out(port, this);
49  getCPUInterface().unregister_IO_In (port, this);
50  }
51  }
52  assert(devices[id]);
53  devices[id] = nullptr;
54 }
55 
56 void MSXDeviceSwitch::reset(EmuTime::param /*time*/)
57 {
58  selected = 0;
59 }
60 
61 byte MSXDeviceSwitch::readIO(word port, EmuTime::param time)
62 {
63  if (devices[selected]) {
64  return devices[selected]->readSwitchedIO(port, time);
65  } else {
66  return 0xFF;
67  }
68 }
69 
70 byte MSXDeviceSwitch::peekIO(word port, EmuTime::param time) const
71 {
72  if (devices[selected]) {
73  return devices[selected]->peekSwitchedIO(port, time);
74  } else {
75  return 0xFF;
76  }
77 }
78 
79 void MSXDeviceSwitch::writeIO(word port, byte value, EmuTime::param time)
80 {
81  if ((port & 0x0F) == 0x00) {
82  selected = value;
83  } else if (devices[selected]) {
84  devices[selected]->writeSwitchedIO(port, value, time);
85  } else {
86  // ignore
87  }
88 }
89 
90 
91 template<typename Archive>
92 void MSXDeviceSwitch::serialize(Archive& ar, unsigned /*version*/)
93 {
94  ar.template serializeBase<MSXDevice>(*this);
95  ar.serialize("selected", selected);
96 }
98 
99 } // namespace openmsx
openmsx::MSXDevice
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:31
serialize.hh
openmsx::MSXDeviceSwitch::readIO
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: MSXDeviceSwitch.cc:61
openmsx::DeviceConfig
Definition: DeviceConfig.hh:19
openmsx::MSXCPUInterface::register_IO_Out
void register_IO_Out(byte port, MSXDevice *device)
Devices can register their Out ports.
Definition: MSXCPUInterface.cc:350
openmsx::MSXDeviceSwitch::writeIO
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
Definition: MSXDeviceSwitch.cc:79
openmsx::MSXSwitchedDevice
Definition: MSXSwitchedDevice.hh:11
openmsx::MSXDeviceSwitch::serialize
void serialize(Archive &ar, unsigned version)
Definition: MSXDeviceSwitch.cc:92
openmsx::MSXDeviceSwitch
Definition: MSXDeviceSwitch.hh:55
ranges.hh
MSXException.hh
openmsx::MSXDeviceSwitch::unregisterDevice
void unregisterDevice(byte id)
Definition: MSXDeviceSwitch.cc:43
openmsx::MSXDeviceSwitch::MSXDeviceSwitch
MSXDeviceSwitch(const DeviceConfig &config)
Definition: MSXDeviceSwitch.cc:11
openmsx::MSXException
Definition: MSXException.hh:9
ranges::all_of
bool all_of(InputRange &&range, UnaryPredicate pred)
Definition: ranges.hh:119
openmsx::MSXDevice::getCPUInterface
MSXCPUInterface & getCPUInterface() const
Definition: MSXDevice.cc:139
MSXDeviceSwitch.hh
openmsx::MSXSwitchedDevice::readSwitchedIO
virtual byte readSwitchedIO(word port, EmuTime::param time)=0
openmsx::MSXDeviceSwitch::reset
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXDeviceSwitch.cc:56
openmsx::MSXSwitchedDevice::writeSwitchedIO
virtual void writeSwitchedIO(word port, byte value, EmuTime::param time)=0
MSXSwitchedDevice.hh
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::MSXSwitchedDevice::peekSwitchedIO
virtual byte peekSwitchedIO(word port, EmuTime::param time) const =0
openmsx::MSXCPUInterface::register_IO_In
void register_IO_In(byte port, MSXDevice *device)
Devices can register their In ports.
Definition: MSXCPUInterface.cc:338
openmsx::MSXDeviceSwitch::registerDevice
void registerDevice(byte id, MSXSwitchedDevice *device)
Definition: MSXDeviceSwitch.cc:26
openmsx::MSXCPUInterface::unregister_IO_In
void unregister_IO_In(byte port, MSXDevice *device)
Definition: MSXCPUInterface.cc:344
openmsx::MSXDeviceSwitch::~MSXDeviceSwitch
~MSXDeviceSwitch() override
Definition: MSXDeviceSwitch.cc:19
openmsx::word
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
MSXCPUInterface.hh
openmsx::MSXCPUInterface::unregister_IO_Out
void unregister_IO_Out(byte port, MSXDevice *device)
Definition: MSXCPUInterface.cc:356
ranges::fill
void fill(ForwardRange &&range, const T &value)
Definition: ranges.hh:191
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
openmsx::MSXDeviceSwitch::peekIO
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: MSXDeviceSwitch.cc:70