OXYGENHUB
◆ main openmsx / src / sound / YM2413OriginalNukeYKT.cc
2.8 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "YM2413OriginalNukeYKT.hh"
2
3
#include "narrow.hh"
4
#include "ranges.hh"
5
#include "serialize.hh"
6
#include "xrange.hh"
7
8
#include <algorithm>
9
#include <array>
10
#include <cassert>
11
12
namespace openmsx {
13
namespace YM2413OriginalNukeYKT {
14
15
YM2413::YM2413()
16
{
17
	reset();
18
}
19
20
void YM2413::reset()
21
{
22
	OPLL_Reset(&opll, opll_type_ym2413b);
23
	std::ranges::fill(regs, 0);
24
}
25
26
void YM2413::generateChannels(std::span<float*, 9 + 5> out_, uint32_t n)
27
{
28
	std::array<float*, 9 + 5> out;
29
	copy_to_range(out_, out);
30
31
	auto f = [&] {
32
		std::array<int32_t, 2> buf;
33
		OPLL_Clock(&opll, buf.data());
34
		switch (opll.cycles) {
35
			case  0: *out[ 9]++ += narrow_cast<float>(buf[1] * 2); break;
36
			case  1: *out[10]++ += narrow_cast<float>(buf[1] * 2); break;
37
			case  2: *out[ 6]++ += narrow_cast<float>(buf[0]);
38
				 *out[11]++ += narrow_cast<float>(buf[1] * 2); break;
39
			case  3: *out[ 7]++ += narrow_cast<float>(buf[0]);
40
				 *out[12]++ += narrow_cast<float>(buf[1] * 2); break;
41
			case  4: *out[ 8]++ += narrow_cast<float>(buf[0]);
42
				 *out[13]++ += narrow_cast<float>(buf[1] * 2); break;
43
			case  8: *out[ 0]++ += narrow_cast<float>(buf[0]);     break;
44
			case  9: *out[ 1]++ += narrow_cast<float>(buf[0]);     break;
45
			case 10: *out[ 2]++ += narrow_cast<float>(buf[0]);     break;
46
			case 14: *out[ 3]++ += narrow_cast<float>(buf[0]);     break;
47
			case 15: *out[ 4]++ += narrow_cast<float>(buf[0]);     break;
48
			case 16: *out[ 5]++ += narrow_cast<float>(buf[0]);     break;
49
		}
50
	};
51
52
	assert(n != 0);
53
	for (auto& write : writes) {
54
		if (write.port != uint8_t(-1)) {
55
			OPLL_Write(&opll, write.port, write.value);
56
			write.port = uint8_t(-1);
57
		}
58
		f();
59
	}
60
	repeat((n - 1) * 18, f);
61
62
	allowed_offset = std::max<int>(0, allowed_offset - 18); // see writePort()
63
}
64
65
void YM2413::writePort(bool port, uint8_t value, int cycle_offset)
66
{
67
	// see comments in YM2413NukeYKT.cc
68
	if (speedUpHack) [[unlikely]] {
69
		while (cycle_offset < allowed_offset) [[unlikely]] {
70
			float d = 0.0f;
71
			std::array<float*, 9 + 5> dummy;
72
			std::ranges::fill(dummy, &d);
73
			generateChannels(dummy, 1);
74
		}
75
		allowed_offset = ((port ? 84 : 12) / 4) + cycle_offset;
76
	}
77
78
	writes[cycle_offset] = {.port = port, .value = value};
79
80
	// only needed for peekReg()
81
	if (port == 0) {
82
		latch = value & 63;
83
	} else {
84
		regs[latch] = value;
85
	}
86
}
87
88
void YM2413::pokeReg(uint8_t /*reg*/, uint8_t /*value*/)
89
{
90
	// not supported
91
}
92
93
std::span<const uint8_t, 64> YM2413::peekRegs() const
94
{
95
	return regs;
96
}
97
98
float YM2413::getAmplificationFactor() const
99
{
100
	return 1.0f / 256.0f;
101
}
102
103
void YM2413::setSpeed(double speed)
104
{
105
	speedUpHack = speed > 1.0;
106
}
107
108
template<typename Archive>
109
void YM2413::serialize(Archive& /*ar*/, unsigned /*version*/)
110
{
111
	// Not implemented
112
}
113
114
} // namespace OriginalNuke
115
116
using YM2413OriginalNukeYKT::YM2413;
117
INSTANTIATE_SERIALIZE_METHODS(YM2413);
118
REGISTER_POLYMORPHIC_INITIALIZER(YM2413Core, YM2413, "YM2413-Original-NukeYKT");
119
120
} // namespace openmsx