OXYGENHUB
◆ main openmsx / src / serial / MusicModuleMIDI.cc
2.8 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "MusicModuleMIDI.hh"
2
3
#include "serialize.hh"
4
5
namespace openmsx {
6
7
// MSX interface:
8
// port R/W
9
// 0    W    Control Register
10
// 1    W    Transmit Data Register
11
// 4    R    Status Register
12
// 5    R    Receive Data Register
13
14
// Some existing Music-Module detection routines:
15
// - fac demo 5: does OUT 0,3 : OUT 0,21 : INP(4) and expects to read 2
16
// - tetris 2 special edition: does INP(4) and expects to read 0
17
// - Synthesix: does INP(4), expects 0; OUT 0,3 : OUT 0,21: INP(4) and expects
18
//   bit 1 to be 1 and bit 2, 3 and 7 to be 0. Then does OUT 5,0xFE : INP(4)
19
//   and expects bit 1 to be 0.
20
// I did some _very_basic_ investigation and found the following:
21
// - after a reset reading from port 4 returns 0
22
// - after initializing the control register, reading port 4 returns 0 (of
23
//   course this will change when you start to actually receive/transmit data)
24
// - writing any value with the lower 2 bits set to 1 returns to the initial
25
//   state, and reading port 4 again returns 0.
26
// -  ?INP(4) : OUT0,3 : ?INP(4) : OUT0,21 : ? INP(4) : OUT0,3 :  ?INP(4)
27
//    outputs: 0, 0, 2, 0
28
29
MusicModuleMIDI::MusicModuleMIDI(const DeviceConfig& config)
30
	: MSXDevice(config)
31
	, mc6850(MSXDevice::getName(), getMotherBoard(), 500000) // 500 kHz
32
{
33
	reset(getCurrentTime());
34
}
35
36
void MusicModuleMIDI::reset(EmuTime time)
37
{
38
	mc6850.reset(time);
39
}
40
41
uint8_t MusicModuleMIDI::readIO(uint16_t port, EmuTime /*time*/)
42
{
43
	switch (port & 0x1) {
44
	case 0:
45
		return mc6850.readStatusReg();
46
	case 1:
47
		return mc6850.readDataReg();
48
	}
49
	UNREACHABLE;
50
}
51
52
uint8_t MusicModuleMIDI::peekIO(uint16_t port, EmuTime /*time*/) const
53
{
54
	switch (port & 0x1) {
55
	case 0:
56
		return mc6850.peekStatusReg();
57
	case 1:
58
		return mc6850.peekDataReg();
59
	}
60
	UNREACHABLE;
61
}
62
63
void MusicModuleMIDI::writeIO(uint16_t port, uint8_t value, EmuTime time)
64
{
65
	switch (port & 0x01) {
66
	case 0:
67
		mc6850.writeControlReg(value, time);
68
		break;
69
	case 1:
70
		mc6850.writeDataReg(value, time);
71
		break;
72
	}
73
}
74
75
// versions 1-3: were for type "MC6850", see that class for details
76
// version 4: first version for "MusicModuleMIDI"
77
template<typename Archive>
78
void MusicModuleMIDI::serialize(Archive& ar, unsigned version)
79
{
80
	ar.template serializeBase<MSXDevice>(*this);
81
	if (ar.versionAtLeast(version, 4)) {
82
		ar.serialize("MC6850", mc6850);
83
	} else {
84
		// MC6850 members were serialized as direct children of the
85
		// <device> tag, without an intermediate <MC6850> tag.
86
		mc6850.serialize(ar, version);
87
	}
88
}
89
INSTANTIATE_SERIALIZE_METHODS(MusicModuleMIDI);
90
REGISTER_MSXDEVICE(MusicModuleMIDI, "MusicModuleMIDI");
91
92
// For backwards compatiblity, also register this class with the old name (only
93
// needed for loading from disk). Versions 1-3 use the old name "MC6850",
94
// version 4 (and above) use the name "MusicModuleMIDI".
95
static const RegisterInitializerHelper<XmlInputArchive, MusicModuleMIDI> registerbwCompat("MC6850");
96
97
} // namespace openmsx