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