OXYGENHUB
◆ main openmsx / src / MSXDeviceSwitch.cc
1.9 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "MSXDeviceSwitch.hh"
2
3
#include "MSXCPUInterface.hh"
4
#include "MSXException.hh"
5
#include "MSXSwitchedDevice.hh"
6
7
#include "serialize.hh"
8
9
#include <algorithm>
10
#include <cassert>
11
12
namespace openmsx {
13
14
MSXDeviceSwitch::MSXDeviceSwitch(const DeviceConfig& config)
15
	: MSXDevice(config)
16
{
17
	std::ranges::fill(devices, nullptr);
18
	reset(EmuTime::dummy());
19
}
20
21
MSXDeviceSwitch::~MSXDeviceSwitch()
22
{
23
	// all devices must be unregistered
24
	assert(std::ranges::all_of(devices, [](auto* dev) { return dev == nullptr; }));
25
	assert(count == 0);
26
}
27
28
void MSXDeviceSwitch::registerDevice(byte id, MSXSwitchedDevice* device)
29
{
30
	if (devices[id]) {
31
		// TODO implement multiplexing
32
		throw MSXException(
33
			"Already have a switched device with id ", int(id));
34
	}
35
	devices[id] = device;
36
	if (count == 0) {
37
		getCPUInterface().register_IO_InOut_range(0x40, 16, this);
38
	}
39
	++count;
40
}
41
42
void MSXDeviceSwitch::unregisterDevice(byte id)
43
{
44
	--count;
45
	if (count == 0) {
46
		getCPUInterface().unregister_IO_InOut_range(0x40, 16, this);
47
	}
48
	assert(devices[id]);
49
	devices[id] = nullptr;
50
}
51
52
void MSXDeviceSwitch::reset(EmuTime /*time*/)
53
{
54
	selected = 0;
55
}
56
57
byte MSXDeviceSwitch::readIO(uint16_t port, EmuTime time)
58
{
59
	if (devices[selected]) {
60
		return devices[selected]->readSwitchedIO(port, time);
61
	} else {
62
		return 0xFF;
63
	}
64
}
65
66
byte MSXDeviceSwitch::peekIO(uint16_t port, EmuTime time) const
67
{
68
	if (devices[selected]) {
69
		return devices[selected]->peekSwitchedIO(port, time);
70
	} else {
71
		return 0xFF;
72
	}
73
}
74
75
void MSXDeviceSwitch::writeIO(uint16_t port, byte value, EmuTime time)
76
{
77
	if ((port & 0x0F) == 0x00) {
78
		selected = value;
79
	} else if (devices[selected]) {
80
		devices[selected]->writeSwitchedIO(port, value, time);
81
	} else {
82
		// ignore
83
	}
84
}
85
86
87
template<typename Archive>
88
void MSXDeviceSwitch::serialize(Archive& ar, unsigned /*version*/)
89
{
90
	ar.template serializeBase<MSXDevice>(*this);
91
	ar.serialize("selected", selected);
92
}
93
INSTANTIATE_SERIALIZE_METHODS(MSXDeviceSwitch);
94
95
} // namespace openmsx