OXYGENHUB
◆ main openmsx / src / sound / MSXAudio.cc
3.2 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "MSXAudio.hh"
2
3
#include "DACSound8U.hh"
4
#include "Y8950Periphery.hh"
5
6
#include "serialize.hh"
7
8
#include "StringOp.hh"
9
10
#include <memory>
11
12
namespace openmsx {
13
14
// MSXAudio
15
16
MSXAudio::MSXAudio(const DeviceConfig& config)
17
	: MSXDevice(config)
18
	, y8950(getName(), config,
19
	        config.getChildDataAsInt("sampleram", 256) * 1024,
20
	        getCurrentTime(), *this)
21
{
22
	auto type = config.getChildData("type", "philips");
23
	if (StringOp::casecmp cmp; cmp(type, "philips")) {
24
		dac = std::make_unique<DACSound8U>(
25
			getName() + " 8-bit DAC", "MSX-AUDIO 8-bit DAC",
26
			config);
27
	}
28
	powerUp(getCurrentTime());
29
}
30
31
MSXAudio::~MSXAudio()
32
{
33
	// delete soon, because PanasonicAudioPeriphery still uses
34
	// this object in its destructor
35
	periphery.reset();
36
}
37
38
Y8950Periphery& MSXAudio::createPeriphery(const std::string& soundDeviceName)
39
{
40
	periphery = Y8950PeripheryFactory::create(
41
		*this, getDeviceConfig2(), soundDeviceName);
42
	return *periphery;
43
}
44
45
void MSXAudio::powerUp(EmuTime time)
46
{
47
	y8950.clearRam();
48
	reset(time);
49
}
50
51
void MSXAudio::reset(EmuTime time)
52
{
53
	y8950.reset(time);
54
	periphery->reset();
55
	registerLatch = 0; // TODO check
56
}
57
58
byte MSXAudio::readIO(uint16_t port, EmuTime time)
59
{
60
	if ((port & 0xE8) == 0x08) {
61
		// read DAC
62
		return 0xFF;
63
	} else {
64
		return (port & 1) ? y8950.readReg(registerLatch, time)
65
		                  : y8950.readStatus(time);
66
	}
67
}
68
69
byte MSXAudio::peekIO(uint16_t port, EmuTime time) const
70
{
71
	if ((port & 0xE8) == 0x08) {
72
		// read DAC
73
		return 0xFF; // read always returns 0xFF
74
	} else {
75
		return (port & 1) ? y8950.peekReg(registerLatch, time)
76
		                  : y8950.peekStatus(time);
77
	}
78
}
79
80
void MSXAudio::writeIO(uint16_t port, byte value, EmuTime time)
81
{
82
	if ((port & 0xE8) == 0x08) {
83
		dacValue = value;
84
		if (dacEnabled) {
85
			assert(dac);
86
			dac->writeDAC(dacValue, time);
87
		}
88
	} else if ((port & 0x01) == 0) {
89
		// 0xC0 or 0xC2
90
		registerLatch = value;
91
	} else {
92
		// 0xC1 or 0xC3
93
		y8950.writeReg(registerLatch, value, time);
94
	}
95
}
96
97
byte MSXAudio::readMem(uint16_t address, EmuTime time)
98
{
99
	return periphery->readMem(address, time);
100
}
101
byte MSXAudio::peekMem(uint16_t address, EmuTime time) const
102
{
103
	return periphery->peekMem(address, time);
104
}
105
void MSXAudio::writeMem(uint16_t address, byte value, EmuTime time)
106
{
107
	periphery->writeMem(address, value, time);
108
}
109
const byte* MSXAudio::getReadCacheLine(uint16_t start) const
110
{
111
	return periphery->getReadCacheLine(start);
112
}
113
byte* MSXAudio::getWriteCacheLine(uint16_t start)
114
{
115
	return periphery->getWriteCacheLine(start);
116
}
117
118
void MSXAudio::enableDAC(bool enable, EmuTime time)
119
{
120
	if ((dacEnabled != enable) && dac) {
121
		dacEnabled = enable;
122
		byte value = dacEnabled ? dacValue : 0x80;
123
		dac->writeDAC(value, time);
124
	}
125
}
126
127
template<typename Archive>
128
void MSXAudio::serialize(Archive& ar, unsigned /*version*/)
129
{
130
	ar.serializePolymorphic("periphery", *periphery);
131
	ar.serialize("Y8950",         y8950,
132
	             "registerLatch", registerLatch,
133
	             "dacValue",      dacValue,
134
	             "dacEnabled",    dacEnabled);
135
136
	if constexpr (Archive::IS_LOADER) {
137
		// restore dac status
138
		if (dacEnabled) {
139
			assert(dac);
140
			dac->writeDAC(dacValue, getCurrentTime());
141
		}
142
	}
143
}
144
INSTANTIATE_SERIALIZE_METHODS(MSXAudio);
145
REGISTER_MSXDEVICE(MSXAudio, "MSX-Audio");
146
147
} // namespace openmsx