openMSX
YMF278.cc
Go to the documentation of this file.
1// Based on ymf278b.c written by R. Belmont and O. Galibert
2
3// Improved by Valley Bell, 2018
4// Thanks to niekniek and l_oliveira for providing recordings from OPL4 hardware.
5// Thanks to superctr and wouterv for discussing changes.
6//
7// Improvements:
8// - added TL interpolation, recordings show that internal TL levels are 0x00..0xff
9// - fixed ADSR speeds, attack rate 15 is now instant
10// - correct clamping of intermediate Rate Correction values
11// - emulation of "loop glitch" (going out-of-bounds by playing a sample faster than it the loop is long)
12// - made calculation of sample position cleaner and closer to how the HW works
13// - increased output resolution from TL (0.375dB) to envelope (0.09375dB)
14// - fixed volume table -6dB steps are done using bit shifts, steps in between are multiplicators
15// - made octave -8 freeze the sample
16// - verified that TL and envelope levels are applied separately, both go silent at -60dB
17// - implemented pseudo-reverb and damping according to manual
18// - made pseudo-reverb ignore Rate Correction (real hardware ignores it)
19// - reimplemented LFO, speed exactly matches the formulas that were probably used when creating the manual
20// - fixed LFO (tremolo) amplitude modulation
21// - made LFO vibrato and tremolo accurate to hardware
22//
23// Known issues:
24// - Octave -8 was only tested with fnum 0. Other fnum values might behave differently.
25
26// This class doesn't model a full YMF278B chip. Instead it only models the
27// wave part. The FM part in modeled in YMF262 (it's almost 100% compatible,
28// the small differences are handled in YMF262). The status register and
29// interaction with the FM registers (e.g. the NEW2 bit) is handled in the
30// YMF278B class.
31
32#include "YMF278.hh"
33
34#include "DeviceConfig.hh"
35#include "MSXException.hh"
36#include "MSXMotherBoard.hh"
37#include "serialize.hh"
38
39#include "enumerate.hh"
40#include "narrow.hh"
41#include "one_of.hh"
42#include "outer.hh"
43#include "ranges.hh"
44#include "xrange.hh"
45
46#include <algorithm>
47
48namespace openmsx {
49
50// envelope output entries
51// fixed to match recordings from actual OPL4 -Valley Bell
52static constexpr int MAX_ATT_INDEX = 0x280; // makes attack phase right and also goes well with "envelope stops at -60dB"
53static constexpr int MIN_ATT_INDEX = 0;
54static constexpr int TL_SHIFT = 2; // envelope values are 4x as fine as TL levels
55
56static constexpr unsigned LFO_SHIFT = 18; // LFO period of up to 0x40000 sample
57static constexpr unsigned LFO_PERIOD = 1 << LFO_SHIFT;
58
59// Envelope Generator phases
60static constexpr int EG_ATT = 4;
61static constexpr int EG_DEC = 3;
62static constexpr int EG_SUS = 2;
63static constexpr int EG_REL = 1;
64static constexpr int EG_OFF = 0;
65// these 2 are only used in old savestates (and are converted to EG_REL on load)
66static constexpr int EG_REV = 5; // pseudo reverb
67static constexpr int EG_DMP = 6; // damp
68
69// Pan values, units are -3dB, i.e. 8.
70static constexpr std::array<uint8_t, 16> pan_left = {
71 0, 8, 16, 24, 32, 40, 48, 255, 255, 0, 0, 0, 0, 0, 0, 0
72};
73static constexpr std::array<uint8_t, 16> pan_right = {
74 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 48, 40, 32, 24, 16, 8
75};
76
77// decay level table (3dB per step)
78// 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)
79static constexpr int16_t SC(int dB) { return int16_t(dB / 3 * 0x20); }
80static constexpr std::array<int16_t, 16> dl_tab = {
81 SC( 0), SC( 3), SC( 6), SC( 9), SC(12), SC(15), SC(18), SC(21),
82 SC(24), SC(27), SC(30), SC(33), SC(36), SC(39), SC(42), SC(93)
83};
84
85static constexpr uint8_t RATE_STEPS = 8;
86static constexpr std::array<uint8_t, 15 * RATE_STEPS> eg_inc = {
87//cycle:0 1 2 3 4 5 6 7
88 0, 1, 0, 1, 0, 1, 0, 1, // 0 rates 00..12 0 (increment by 0 or 1)
89 0, 1, 0, 1, 1, 1, 0, 1, // 1 rates 00..12 1
90 0, 1, 1, 1, 0, 1, 1, 1, // 2 rates 00..12 2
91 0, 1, 1, 1, 1, 1, 1, 1, // 3 rates 00..12 3
92
93 1, 1, 1, 1, 1, 1, 1, 1, // 4 rate 13 0 (increment by 1)
94 1, 1, 1, 2, 1, 1, 1, 2, // 5 rate 13 1
95 1, 2, 1, 2, 1, 2, 1, 2, // 6 rate 13 2
96 1, 2, 2, 2, 1, 2, 2, 2, // 7 rate 13 3
97
98 2, 2, 2, 2, 2, 2, 2, 2, // 8 rate 14 0 (increment by 2)
99 2, 2, 2, 4, 2, 2, 2, 4, // 9 rate 14 1
100 2, 4, 2, 4, 2, 4, 2, 4, // 10 rate 14 2
101 2, 4, 4, 4, 2, 4, 4, 4, // 11 rate 14 3
102
103 4, 4, 4, 4, 4, 4, 4, 4, // 12 rates 15 0, 15 1, 15 2, 15 3 for decay
104 8, 8, 8, 8, 8, 8, 8, 8, // 13 rates 15 0, 15 1, 15 2, 15 3 for attack (zero time)
105 0, 0, 0, 0, 0, 0, 0, 0, // 14 infinity rates for attack and decay(s)
106};
107
108[[nodiscard]] static constexpr uint8_t O(int a) { return narrow<uint8_t>(a * RATE_STEPS); }
109static constexpr std::array<uint8_t, 64> eg_rate_select = {
110 O(14),O(14),O(14),O(14), // inf rate
111 O( 0),O( 1),O( 2),O( 3),
112 O( 0),O( 1),O( 2),O( 3),
113 O( 0),O( 1),O( 2),O( 3),
114 O( 0),O( 1),O( 2),O( 3),
115 O( 0),O( 1),O( 2),O( 3),
116 O( 0),O( 1),O( 2),O( 3),
117 O( 0),O( 1),O( 2),O( 3),
118 O( 0),O( 1),O( 2),O( 3),
119 O( 0),O( 1),O( 2),O( 3),
120 O( 0),O( 1),O( 2),O( 3),
121 O( 0),O( 1),O( 2),O( 3),
122 O( 0),O( 1),O( 2),O( 3),
123 O( 4),O( 5),O( 6),O( 7),
124 O( 8),O( 9),O(10),O(11),
125 O(12),O(12),O(12),O(12),
126};
127
128// rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
129// shift 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
130// mask 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0
131static constexpr std::array<uint8_t, 64> eg_rate_shift = {
132 12, 12, 12, 12,
133 11, 11, 11, 11,
134 10, 10, 10, 10,
135 9, 9, 9, 9,
136 8, 8, 8, 8,
137 7, 7, 7, 7,
138 6, 6, 6, 6,
139 5, 5, 5, 5,
140 4, 4, 4, 4,
141 3, 3, 3, 3,
142 2, 2, 2, 2,
143 1, 1, 1, 1,
144 0, 0, 0, 0,
145 0, 0, 0, 0,
146 0, 0, 0, 0,
147 0, 0, 0, 0,
148};
149
150
151// number of steps the LFO counter advances per sample
152// LFO frequency (Hz) -> LFO counter steps per sample
153[[nodiscard]] static constexpr int L(double a) { return int((LFO_PERIOD * a) / 44100.0 + 0.5); }
154static constexpr std::array<int, 8> lfo_period = {
155 L(0.168), // step: 1, period: 262144 samples
156 L(2.019), // step: 12, period: 21845 samples
157 L(3.196), // step: 19, period: 13797 samples
158 L(4.206), // step: 25, period: 10486 samples
159 L(5.215), // step: 31, period: 8456 samples
160 L(5.888), // step: 35, period: 7490 samples
161 L(6.224), // step: 37, period: 7085 samples
162 L(7.066), // step: 42, period: 6242 samples
163};
164
165
166// formula used by Yamaha docs:
167// vib_depth_cents(x) = (log2(0x400 + x) - 10) * 1200
168static constexpr std::array<int16_t, 8> vib_depth = {
169 0, // 0.000 cents
170 2, // 3.378 cents
171 3, // 5.065 cents
172 4, // 6.750 cents
173 6, // 10.114 cents
174 12, // 20.170 cents
175 24, // 40.106 cents
176 48, // 79.307 cents
177};
178
179
180// formula used by Yamaha docs:
181// am_depth_db(x) = (x-1) / 0x40 * 6.0
182// They use (x-1), because the depth is multiplied with the AM counter, which has a range of 0..0x7F.
183// Thus the maximum attenuation with x=0x80 is (0x7F * 0x80) >> 7 = 0x7F.
184// reversed formula:
185// am_depth(dB) = round(dB / 6.0 * 0x40) + 1
186static constexpr std::array<uint8_t, 8> am_depth = {
187 0x00, // 0.000 dB
188 0x14, // 1.781 dB
189 0x20, // 2.906 dB
190 0x28, // 3.656 dB
191 0x30, // 4.406 dB
192 0x40, // 5.906 dB
193 0x50, // 7.406 dB
194 0x80, // 11.910 dB
195};
196
197
198YMF278::Slot::Slot()
199{
200 reset();
201}
202
203// Sign extend a 4-bit value to int8_t
204// require: x in range [0..15]
205[[nodiscard]] static constexpr int8_t sign_extend_4(int x)
206{
207 return narrow<int8_t>((x ^ 8) - 8);
208}
209
210// Params: oct in [-8 .. +7]
211// fn in [ 0 .. 1023]
212// We want to interpret oct as a signed 4-bit number and calculate
213// ((fn | 1024) + vib) << (5 + sign_extend_4(oct))
214// Though in this formula the shift can go over a negative distance (in that
215// case we should shift in the other direction).
216[[nodiscard]] static constexpr unsigned calcStep(int8_t oct, uint16_t fn, int16_t vib = 0)
217{
218 if (oct == -8) return 0;
219 unsigned t = (fn + 1024 + vib) << (8 + oct); // use '+' iso '|' (generates slightly better code)
220 return t >> 3; // was shifted 3 positions too far
221}
222
223void YMF278::Slot::reset()
224{
225 wave = FN = TLdest = TL = pan = vib = AM = 0;
226 OCT = 0;
227 DL = 0;
228 AR = D1R = D2R = RC = RR = 0;
229 PRVB = keyon = DAMP = false;
230 stepPtr = 0;
231 step = calcStep(OCT, FN);
232 bits = 0;
233 startAddr = 0;
234 loopAddr = endAddr = 0;
235 env_vol = MAX_ATT_INDEX;
236
237 lfo_active = false;
238 lfo_cnt = 0;
239 lfo = 0;
240
241 state = EG_OFF;
242
243 // not strictly needed, but avoid UMR on savestate
244 pos = 0;
245}
246
247uint8_t YMF278::Slot::compute_rate(int val) const
248{
249 if (val == 0) {
250 return 0;
251 } else if (val == 15) {
252 return 63;
253 }
254 int res = val * 4;
255 if (RC != 15) {
256 // clamping verified with HW tests -Valley Bell
257 res += 2 * std::clamp(OCT + RC, 0, 15);
258 res += (FN & 0x200) ? 1 : 0;
259 }
260 return narrow<uint8_t>(std::clamp(res, 0, 63));
261}
262
263uint8_t YMF278::Slot::compute_decay_rate(int val) const
264{
265 if (DAMP) {
266 // damping
267 // The manual lists these values for time and attenuation: (44100 samples/second)
268 // -12dB at 5.8ms, sample 256
269 // -48dB at 8.0ms, sample 352
270 // -72dB at 9.4ms, sample 416
271 // -96dB at 10.9ms, sample 480
272 // This results in these durations and rate values for the respective phases:
273 // 0dB .. -12dB: 256 samples (5.80ms) -> 128 samples per -6dB = rate 48
274 // -12dB .. -48dB: 96 samples (2.18ms) -> 16 samples per -6dB = rate 63
275 // -48dB .. -72dB: 64 samples (1.45ms) -> 16 samples per -6dB = rate 63
276 // -72dB .. -96dB: 64 samples (1.45ms) -> 16 samples per -6dB = rate 63
277 // Damping was verified to ignore rate correction.
278 if (env_vol < dl_tab[4]) {
279 return 48; // 0dB .. -12dB
280 } else {
281 return 63; // -12dB .. -96dB
282 }
283 }
284 if (PRVB) {
285 // pseudo reverb
286 // activated when reaching -18dB, overrides D1R/D2R/RR with reverb rate 5
287 //
288 // The manual is actually a bit unclear and just says "RATE=5",
289 // referring to the D1R/D2R/RR register value. However, later
290 // pages use "RATE" to refer to the "internal" rate, which is
291 // (register * 4) + rate correction. HW recordings prove that
292 // Rate Correction is ignored, so pseudo reverb just sets the
293 // "internal" rate to a value of 4*5 = 20.
294 if (env_vol >= dl_tab[6]) {
295 return 20;
296 }
297 }
298 return compute_rate(val);
299}
300
301int16_t YMF278::Slot::compute_vib() const
302{
303 // verified via hardware recording:
304 // With LFO speed 0 (period 262144 samples), each vibrato step takes
305 // 4096 samples.
306 // -> 64 steps total
307 // Also, with vibrato depth 7 (80 cents) and an F-Num of 0x400, the
308 // final F-Nums are: 0x400 .. 0x43C, 0x43C .. 0x400, 0x400 .. 0x3C4,
309 // 0x3C4 .. 0x400
310 auto lfo_fm = narrow<int16_t>(lfo_cnt / (LFO_PERIOD / 0x40));
311 // results in +0x00..+0x0F, +0x0F..+0x00, -0x00..-0x0F, -0x0F..-0x00
312 if (lfo_fm & 0x10) lfo_fm ^= 0x1F;
313 if (lfo_fm & 0x20) lfo_fm = narrow<int16_t>(-(lfo_fm & 0x0F));
314
315 return narrow<int16_t>((lfo_fm * vib_depth[vib]) / 12);
316}
317
318uint16_t YMF278::Slot::compute_am() const
319{
320 // verified via hardware recording:
321 // With LFO speed 0 (period 262144 samples), each tremolo step takes
322 // 1024 samples.
323 // -> 256 steps total
324 auto lfo_am = narrow<uint16_t>(lfo_cnt / (LFO_PERIOD / 0x100));
325 // results in 0x00..0x7F, 0x7F..0x00
326 if (lfo_am >= 0x80) lfo_am ^= 0xFF;
327
328 return narrow<uint16_t>((lfo_am * am_depth[AM]) >> 7);
329}
330
331
332void YMF278::advance()
333{
334 eg_cnt++;
335
336 // modulo counters for volume interpolation
337 auto tl_int_cnt = eg_cnt % 9; // 0 .. 8
338 auto tl_int_step = (eg_cnt / 9) % 3; // 0 .. 2
339
340 for (auto& op : slots) {
341 // volume interpolation
342 if (tl_int_cnt == 0) {
343 if (tl_int_step == 0) {
344 // decrease volume by one step every 27 samples
345 if (op.TL < op.TLdest) ++op.TL;
346 } else {
347 // increase volume by one step every 13.5 samples
348 if (op.TL > op.TLdest) --op.TL;
349 }
350 }
351
352 if (op.lfo_active) {
353 op.lfo_cnt = (op.lfo_cnt + lfo_period[op.lfo]) & (LFO_PERIOD - 1);
354 }
355
356 // Envelope Generator
357 switch (op.state) {
358 case EG_ATT: { // attack phase
359 uint8_t rate = op.compute_rate(op.AR);
360 // Verified by HW recording (and matches Nemesis' tests of the YM2612):
361 // AR = 0xF during KeyOn results in instant switch to EG_DEC. (see keyOnHelper)
362 // Setting AR = 0xF while the attack phase is in progress freezes the envelope.
363 if (rate >= 63) {
364 break;
365 }
366 uint8_t shift = eg_rate_shift[rate];
367 if (!(eg_cnt & ((1 << shift) - 1))) {
368 uint8_t select = eg_rate_select[rate];
369 // >>4 makes the attack phase's shape match the actual chip -Valley Bell
370 op.env_vol = narrow<int16_t>(op.env_vol + ((~op.env_vol * eg_inc[select + ((eg_cnt >> shift) & 7)]) >> 4));
371 if (op.env_vol <= MIN_ATT_INDEX) {
372 op.env_vol = MIN_ATT_INDEX;
373 // TODO does the real HW skip EG_DEC completely,
374 // or is it active for 1 sample?
375 op.state = op.DL ? EG_DEC : EG_SUS;
376 }
377 }
378 break;
379 }
380 case EG_DEC: { // decay phase
381 uint8_t rate = op.compute_decay_rate(op.D1R);
382 uint8_t shift = eg_rate_shift[rate];
383 if (!(eg_cnt & ((1 << shift) - 1))) {
384 uint8_t select = eg_rate_select[rate];
385 op.env_vol = narrow<int16_t>(op.env_vol + eg_inc[select + ((eg_cnt >> shift) & 7)]);
386 if (op.env_vol >= op.DL) {
387 op.state = (op.env_vol < MAX_ATT_INDEX) ? EG_SUS : EG_OFF;
388 }
389 }
390 break;
391 }
392 case EG_SUS: { // sustain phase
393 uint8_t rate = op.compute_decay_rate(op.D2R);
394 uint8_t shift = eg_rate_shift[rate];
395 if (!(eg_cnt & ((1 << shift) - 1))) {
396 uint8_t select = eg_rate_select[rate];
397 op.env_vol = narrow<int16_t>(op.env_vol + eg_inc[select + ((eg_cnt >> shift) & 7)]);
398 if (op.env_vol >= MAX_ATT_INDEX) {
399 op.env_vol = MAX_ATT_INDEX;
400 op.state = EG_OFF;
401 }
402 }
403 break;
404 }
405 case EG_REL: { // release phase
406 uint8_t rate = op.compute_decay_rate(op.RR);
407 uint8_t shift = eg_rate_shift[rate];
408 if (!(eg_cnt & ((1 << shift) - 1))) {
409 uint8_t select = eg_rate_select[rate];
410 op.env_vol = narrow<int16_t>(op.env_vol + eg_inc[select + ((eg_cnt >> shift) & 7)]);
411 if (op.env_vol >= MAX_ATT_INDEX) {
412 op.env_vol = MAX_ATT_INDEX;
413 op.state = EG_OFF;
414 }
415 }
416 break;
417 }
418 case EG_OFF:
419 // nothing
420 break;
421
422 default:
424 }
425 }
426}
427
428int16_t YMF278::getSample(const Slot& slot, uint16_t pos) const
429{
430 // TODO How does this behave when R#2 bit 0 = 1?
431 // As-if read returns 0xff? (Like for CPU memory reads.) Or is
432 // sound generation blocked at some higher level?
433 switch (slot.bits) {
434 case 0: {
435 // 8 bit
436 return narrow_cast<int16_t>(readMem(slot.startAddr + pos) << 8);
437 }
438 case 1: {
439 // 12 bit
440 unsigned addr = slot.startAddr + ((pos / 2) * 3);
441 if (pos & 1) {
442 return narrow_cast<int16_t>(
443 (readMem(addr + 2) << 8) |
444 (readMem(addr + 1) & 0xF0));
445 } else {
446 return narrow_cast<int16_t>(
447 (readMem(addr + 0) << 8) |
448 ((readMem(addr + 1) << 4) & 0xF0));
449 }
450 }
451 case 2: {
452 // 16 bit
453 unsigned addr = slot.startAddr + (pos * 2);
454 return narrow_cast<int16_t>(
455 (readMem(addr + 0) << 8) |
456 (readMem(addr + 1) << 0));
457 }
458 default:
459 // TODO unspecified
460 return 0;
461 }
462}
463
464uint16_t YMF278::nextPos(const Slot& slot, uint16_t pos, uint16_t increment)
465{
466 // If there is a 4-sample loop and you advance 12 samples per step,
467 // it may exceed the end offset.
468 // This is abused by the "Lizard Star" song to generate noise at 0:52. -Valley Bell
469 pos += increment;
470 if ((uint32_t(pos) + slot.endAddr) >= 0x10000) // check position >= (negated) end address
471 pos += narrow_cast<uint16_t>(slot.endAddr + slot.loopAddr); // This is how the actual chip does it.
472 return pos;
473}
474
475bool YMF278::anyActive()
476{
477 return ranges::any_of(slots, [](auto& op) { return op.state != EG_OFF; });
478}
479
480// In: 'envVol', 0=max volume, others -> -3/32 = -0.09375 dB/step
481// Out: 'x' attenuated by the corresponding factor.
482// Note: microbenchmarks have shown that re-doing this calculation is about the
483// same speed as using a 4kB lookup table.
484static constexpr int vol_factor(int x, unsigned envVol)
485{
486 if (envVol >= MAX_ATT_INDEX) return 0; // hardware clips to silence below -60dB
487 int vol_mul = 0x80 - narrow<int>(envVol & 0x3F); // 0x40 values per 6dB
488 int vol_shift = 7 + narrow<int>(envVol >> 6);
489 return (x * ((0x8000 * vol_mul) >> vol_shift)) >> 15;
490}
491
492void YMF278::setMixLevel(uint8_t x, EmuTime::param time)
493{
494 static constexpr std::array<float, 8> level = {
495 (1.00f / 1), // 0dB
496 (0.75f / 1), // -3dB (approx)
497 (1.00f / 2), // -6dB
498 (0.75f / 2), // -9dB (approx)
499 (1.00f / 4), // -12dB
500 (0.75f / 4), // -15dB (approx)
501 (1.00f / 8), // -18dB
502 0.00f // -inf dB
503 };
504 setSoftwareVolume(level[x & 7], level[(x >> 3) & 7], time);
505}
506
507void YMF278::generateChannels(std::span<float*> bufs, unsigned num)
508{
509 if (!anyActive()) {
510 // TODO update internal state, even if muted
511 // TODO also mute individual channels
512 ranges::fill(bufs, nullptr);
513 return;
514 }
515
516 for (auto j : xrange(num)) {
517 for (auto i : xrange(24)) {
518 auto& sl = slots[i];
519 if (sl.state == EG_OFF) {
520 //bufs[i][2 * j + 0] += 0;
521 //bufs[i][2 * j + 1] += 0;
522 continue;
523 }
524
525 auto sample = narrow_cast<int16_t>(
526 (getSample(sl, sl.pos) * (0x10000 - sl.stepPtr) +
527 getSample(sl, nextPos(sl, sl.pos, 1)) * sl.stepPtr) >> 16);
528 // TL levels are 00..FF internally (TL register value 7F is mapped to TL level FF)
529 // Envelope levels have 4x the resolution (000..3FF)
530 // Volume levels are approximate logarithmic. -6dB result in half volume. Steps in between use linear interpolation.
531 // A volume of -60dB or lower results in silence. (value 0x280..0x3FF).
532 // Recordings from actual hardware indicate that TL level and envelope level are applied separately.
533 // Each of them is clipped to silence below -60dB, but TL+envelope might result in a lower volume. -Valley Bell
534 auto envVol = narrow_cast<uint16_t>(
535 std::min(sl.env_vol + ((sl.lfo_active && sl.AM) ? sl.compute_am() : 0),
536 MAX_ATT_INDEX));
537 int smplOut = vol_factor(vol_factor(sample, envVol), sl.TL << TL_SHIFT);
538
539 // Panning is also done separately. (low-volume TL + low-volume panning goes below -60dB)
540 // I'll be taking wild guess and assume that -3dB is approximated with 75%. (same as with TL and envelope levels)
541 // The same applies to the PCM mix level.
542 int32_t volLeft = pan_left [sl.pan]; // note: register 0xF9 is handled externally
543 int32_t volRight = pan_right[sl.pan];
544 // 0 -> 0x20, 8 -> 0x18, 16 -> 0x10, 24 -> 0x0C, etc. (not using vol_factor here saves array boundary checks)
545 volLeft = (0x20 - (volLeft & 0x0f)) >> (volLeft >> 4);
546 volRight = (0x20 - (volRight & 0x0f)) >> (volRight >> 4);
547
548 bufs[i][2 * j + 0] += narrow_cast<float>((smplOut * volLeft ) >> 5);
549 bufs[i][2 * j + 1] += narrow_cast<float>((smplOut * volRight) >> 5);
550
551 unsigned step = (sl.lfo_active && sl.vib)
552 ? calcStep(sl.OCT, sl.FN, sl.compute_vib())
553 : sl.step;
554 sl.stepPtr += step;
555
556 if (sl.stepPtr >= 0x10000) {
557 sl.pos = nextPos(sl, sl.pos, narrow<uint16_t>(sl.stepPtr >> 16));
558 sl.stepPtr &= 0xffff;
559 }
560 }
561 advance();
562 }
563}
564
565void YMF278::keyOnHelper(YMF278::Slot& slot) const
566{
567 // Unlike FM, the envelope level is reset. (And it makes sense, because you restart the sample.)
568 slot.env_vol = MAX_ATT_INDEX;
569 if (slot.compute_rate(slot.AR) < 63) {
570 slot.state = EG_ATT;
571 } else {
572 // Nuke.YKT verified that the FM part does it exactly this way,
573 // and the OPL4 manual says it's instant as well.
574 slot.env_vol = MIN_ATT_INDEX;
575 // see comment in 'case EG_ATT' in YMF278::advance()
576 slot.state = slot.DL ? EG_DEC : EG_SUS;
577 }
578 slot.stepPtr = 0;
579 slot.pos = 0;
580}
581
582void YMF278::writeReg(uint8_t reg, uint8_t data, EmuTime::param time)
583{
584 updateStream(time); // TODO optimize only for regs that directly influence sound
585 writeRegDirect(reg, data, time);
586}
587
588void YMF278::writeRegDirect(uint8_t reg, uint8_t data, EmuTime::param time)
589{
590 // Handle slot registers specifically
591 if (reg >= 0x08 && reg <= 0xF7) {
592 int sNum = (reg - 8) % 24;
593 auto& slot = slots[sNum];
594 switch ((reg - 8) / 24) {
595 case 0: {
596 slot.wave = (slot.wave & 0x100) | data;
597 int waveTblHdr = (regs[2] >> 2) & 0x7;
598 int base = (slot.wave < 384 || !waveTblHdr) ?
599 (slot.wave * 12) :
600 (waveTblHdr * 0x80000 + ((slot.wave - 384) * 12));
601 std::array<uint8_t, 12> buf;
602 for (auto i : xrange(12)) {
603 // TODO What if R#2 bit 0 = 1?
604 // See also getSample()
605 buf[i] = readMem(base + i);
606 }
607 slot.bits = (buf[0] & 0xC0) >> 6;
608 slot.startAddr = buf[2] | (buf[1] << 8) | ((buf[0] & 0x3F) << 16);
609 slot.loopAddr = uint16_t(buf[4] | (buf[3] << 8));
610 slot.endAddr = uint16_t(buf[6] | (buf[5] << 8));
611 for (auto i : xrange(7, 12)) {
612 // Verified on real YMF278:
613 // After tone loading, if you read these
614 // registers, their value actually has changed.
615 writeRegDirect(narrow<uint8_t>(8 + sNum + (i - 2) * 24), buf[i], time);
616 }
617 if (slot.keyon) {
618 keyOnHelper(slot);
619 } else {
620 slot.stepPtr = 0;
621 slot.pos = 0;
622 }
623 break;
624 }
625 case 1: {
626 slot.wave = uint16_t((slot.wave & 0xFF) | ((data & 0x1) << 8));
627 slot.FN = (slot.FN & 0x380) | (data >> 1);
628 slot.step = calcStep(slot.OCT, slot.FN);
629 break;
630 }
631 case 2: {
632 slot.FN = uint16_t((slot.FN & 0x07F) | ((data & 0x07) << 7));
633 slot.PRVB = (data & 0x08) != 0;
634 slot.OCT = sign_extend_4((data & 0xF0) >> 4);
635 slot.step = calcStep(slot.OCT, slot.FN);
636 break;
637 }
638 case 3: {
639 uint8_t t = data >> 1;
640 slot.TLdest = (t != 0x7f) ? t : 0xff; // verified on HW via volume interpolation
641 if (data & 1) {
642 // directly change volume
643 slot.TL = slot.TLdest;
644 } else {
645 // interpolate volume
646 }
647 break;
648 }
649 case 4:
650 if (data & 0x10) {
651 // output to DO1 pin:
652 // this pin is not used in MoonSound
653 // we emulate this by muting the sound
654 slot.pan = 8; // both left/right -inf dB
655 } else {
656 slot.pan = data & 0x0F;
657 }
658
659 if (data & 0x20) {
660 // LFO reset
661 slot.lfo_active = false;
662 slot.lfo_cnt = 0;
663 } else {
664 // LFO activate
665 slot.lfo_active = true;
666 }
667
668 slot.DAMP = (data & 0x40) != 0;
669
670 if (data & 0x80) {
671 if (!slot.keyon) {
672 slot.keyon = true;
673 keyOnHelper(slot);
674 }
675 } else {
676 if (slot.keyon) {
677 slot.keyon = false;
678 slot.state = EG_REL;
679 }
680 }
681 break;
682 case 5:
683 slot.lfo = (data >> 3) & 0x7;
684 slot.vib = data & 0x7;
685 break;
686 case 6:
687 slot.AR = data >> 4;
688 slot.D1R = data & 0xF;
689 break;
690 case 7:
691 slot.DL = dl_tab[data >> 4];
692 slot.D2R = data & 0xF;
693 break;
694 case 8:
695 slot.RC = data >> 4;
696 slot.RR = data & 0xF;
697 break;
698 case 9:
699 slot.AM = data & 0x7;
700 break;
701 }
702 } else {
703 // All non-slot registers
704 switch (reg) {
705 case 0x00: // TEST
706 case 0x01:
707 break;
708
709 case 0x02:
710 // wave-table-header / memory-type / memory-access-mode
711 // Simply store in regs[2]
712 // Immediately write reg here and update memory pointers
713 regs[2] = data;
715 break;
716
717 case 0x03:
718 // Verified on real YMF278:
719 // * Don't update the 'memAdr' variable on writes to
720 // reg 3 and 4. Only store the value in the 'regs'
721 // array for later use.
722 // * The upper 2 bits are not used to address the
723 // external memories (so from a HW pov they don't
724 // matter). But if you read back this register, the
725 // upper 2 bits always read as '0' (even if you wrote
726 // '1'). So we mask the bits here already.
727 data &= 0x3F;
728 break;
729
730 case 0x04:
731 // See reg 3.
732 break;
733
734 case 0x05:
735 // Verified on real YMF278: (see above)
736 // Only writes to reg 5 change the (full) 'memAdr'.
737 memAdr = (regs[3] << 16) | (regs[4] << 8) | data;
738 break;
739
740 case 0x06: // memory data
741 if (regs[2] & 1) {
742 writeMem(memAdr, data);
743 ++memAdr; // no need to mask (again) here
744 } else {
745 // Verified on real YMF278:
746 // - writes are ignored
747 // - memAdr is NOT increased
748 }
749 break;
750
751 case 0xf8: // These are implemented in MSXMoonSound.cc
752 case 0xf9:
753 break;
754 }
755 }
756
757 regs[reg] = data;
758}
759
760uint8_t YMF278::readReg(uint8_t reg)
761{
762 // no need to call updateStream(time)
763 uint8_t result = peekReg(reg);
764 if (reg == 6) {
765 // Memory Data Register
766 if (regs[2] & 1) {
767 // Verified on real YMF278:
768 // memAdr is only increased when 'regs[2] & 1'
769 ++memAdr; // no need to mask (again) here
770 }
771 }
772 return result;
773}
774
775uint8_t YMF278::peekReg(uint8_t reg) const
776{
777 switch (reg) {
778 case 2: // 3 upper bits are device ID
779 return (regs[2] & 0x1F) | 0x20;
780
781 case 6: // Memory Data Register
782 if (regs[2] & 1) {
783 return readMem(memAdr);
784 } else {
785 // Verified on real YMF278
786 return 0xff;
787 }
788
789 default:
790 return regs[reg];
791 }
792}
793
794static constexpr unsigned INPUT_RATE = 44100;
795
796YMF278::YMF278(const std::string& name_, size_t ramSize, const DeviceConfig& config,
797 SetupMemPtrFunc setupMemPtrs_)
798 : ResampledSoundDevice(config.getMotherBoard(), name_, "OPL4 wave-part",
799 24, INPUT_RATE, true)
800 , motherBoard(config.getMotherBoard())
801 , debugRegisters(motherBoard, getName())
802 , debugMemory (motherBoard, getName())
803 , rom(getName() + " ROM", "rom", config)
804 , ram(config, getName() + " RAM", "YMF278 sample RAM", ramSize)
805 , setupMemPtrs(setupMemPtrs_)
806{
807 if (rom.size() != 0x200000) { // 2MB
808 throw MSXException(
809 "Wrong ROM for OPL4 (YMF278B). The ROM (usually "
810 "called yrw801.rom) should have a size of exactly 2MB.");
811 }
812
813 memAdr = 0; // avoid UMR
814 ranges::fill(regs, 0);
815
816 registerSound(config);
817 reset(motherBoard.getCurrentTime()); // must come after registerSound() because of call to setSoftwareVolume() via setMixLevel()
818}
819
824
826{
827 ram.clear(0);
828}
829
830void YMF278::reset(EmuTime::param time)
831{
832 updateStream(time);
833
834 eg_cnt = 0;
835
836 for (auto& op : slots) {
837 op.reset();
838 }
839 regs[2] = 0; // avoid UMR
840 for (int i = 0xf7; i >= 0; --i) { // reverse order to avoid UMR
841 writeRegDirect(narrow<uint8_t>(i), 0, time);
842 }
843 regs[0xf8] = 0x1b; // FM mix-level, see also YMF262 reset
844 regs[0xf9] = 0x00; // Wave mix-level
845 memAdr = 0;
846 setMixLevel(0, time);
847
849}
850
851// The YMF278B chip has 10 chip-select output signals named /MCS0 .. /MSC9.
852// There is a 4MB address space to store samples (e.g. in ROM or RAM). Depending on
853// which address is accessed, one or more of these /MCSx signals get active. And there
854// are two modes for this mapping (controlled via bit 1 in R#2):
855//
856// mode=0 mode=1
857// /MCS0 0x000000-0x1FFFFF 0x000000-0x1FFFFF
858// /MCS1 0x200000-0x3FFFFF 0x000000-0x0FFFFF
859// /MCS2 0x000000-0x0FFFFF 0x100000-0x1FFFFF
860// /MCS3 0x100000-0x1FFFFF 0x200000-0x2FFFFF
861// /MCS4 0x200000-0x2FFFFF 0x200000-0x27FFFF
862// /MCS5 0x300000-0x3FFFFF 0x280000-0x2FFFFF
863// /MCS6 0x200000-0x27FFFF 0x380000-0x39FFFF
864// /MCS7 0x280000-0x2FFFFF 0x3A0000-0x3BFFFF
865// /MCS8 0x300000-0x37FFFF 0x3C0000-0x3DFFFF
866// /MCS9 0x380000-0x3FFFFF 0x3E0000-0x3FFFFF
868{
869 bool mode0 = (regs[2] & 2) == 0;
870 setupMemPtrs(mode0, rom, ram, memPtrs);
871}
872
873uint8_t YMF278::readMem(unsigned address) const
874{
875 // Verified on real YMF278: address space wraps at 4MB.
876 address &= 0x3F'FFFF;
877 if (auto chunk = memPtrs[address >> 17].asOptional()) { // 128kB chunk
878 return (*chunk)[address & 0x1'FFFF];
879 }
880 return 0xFF;
881}
882
883void YMF278::writeMem(unsigned address, uint8_t value)
884{
885 address &= 0x3F'FFFF;
886 if (auto chunk = memPtrs[address >> 17].asOptional()) { // mapped?
887 auto* ptr = chunk->data() + (address & 0x1'ffff);
888 if ((&ram[0] <= ptr) && (ptr < (&ram[0] + ram.size()))) { // points to RAM?
889 // this assumes all RAM is emulated via a single contiguous memory block
890 auto ramOffset = ptr - &ram[0];
891 ram.write(ramOffset, value);
892 }
893 }
894 // ignore writes to non-mapped, or non-RAM regions
895}
896
897// version 1: initial version, some variables were saved as char
898// version 2: serialization framework was fixed to save/load chars as numbers
899// but for backwards compatibility we still load old savestates as
900// characters
901// version 3: 'step' is no longer stored (it is recalculated)
902// version 4:
903// - removed members: 'lfo', 'LD', 'active'
904// - new members 'TLdest', 'keyon', 'DAMP' restored from registers instead of serialized
905// - store 'OCT' sign-extended
906// - store 'endAddr' as 2s complement
907// - removed EG_DMP and EG_REV enum values from 'state'
908// version 5:
909// - re-added 'lfo' member. This is not stored in the savestate, instead it's
910// restored from register values in YMF278::serialize()
911// - removed members 'lfo_step' and ' 'lfo_max'
912// - 'lfo_cnt' has changed meaning (but we don't try to translate old to new meaning)
913// version 6:
914// - removed members: 'sample1', 'sample2'
915template<typename Archive>
916void YMF278::Slot::serialize(Archive& ar, unsigned version)
917{
918 // TODO restore more state from registers
919 ar.serialize("startaddr", startAddr,
920 "loopaddr", loopAddr,
921 "stepptr", stepPtr,
922 "pos", pos,
923 "env_vol", env_vol,
924 "lfo_cnt", lfo_cnt,
925 "DL", DL,
926 "wave", wave,
927 "FN", FN);
928 if (ar.versionAtLeast(version, 4)) {
929 ar.serialize("endaddr", endAddr,
930 "OCT", OCT);
931 } else {
932 unsigned e = 0; ar.serialize("endaddr", e); endAddr = uint16_t((e ^ 0xffff) + 1);
933
934 char O = 0;
935 if (ar.versionAtLeast(version, 2)) {
936 ar.serialize("OCT", O);
937 } else {
938 ar.serializeChar("OCT", O);
939 }
940 OCT = sign_extend_4(O);
941 }
942
943 if (ar.versionAtLeast(version, 2)) {
944 ar.serialize("PRVB", PRVB,
945 "TL", TL,
946 "pan", pan,
947 "vib", vib,
948 "AM", AM,
949 "AR", AR,
950 "D1R", D1R,
951 "D2R", D2R,
952 "RC", RC,
953 "RR", RR);
954 } else {
955 // for backwards compatibility with old savestates
956 char PRVB_ = 0; ar.serializeChar("PRVB", PRVB_); PRVB = PRVB_;
957 char TL_ = 0; ar.serializeChar("TL", TL_ ); TL = TL_;
958 char pan_ = 0; ar.serializeChar("pan", pan_); pan = pan_;
959 char vib_ = 0; ar.serializeChar("vib", vib_); vib = vib_;
960 char AM_ = 0; ar.serializeChar("AM", AM_ ); AM = AM_;
961 char AR_ = 0; ar.serializeChar("AR", AR_ ); AR = AR_;
962 char D1R_ = 0; ar.serializeChar("D1R", D1R_); D1R = D1R_;
963 char D2R_ = 0; ar.serializeChar("D2R", D2R_); D2R = D2R_;
964 char RC_ = 0; ar.serializeChar("RC", RC_ ); RC = RC_;
965 char RR_ = 0; ar.serializeChar("RR", RR_ ); RR = RR_;
966 }
967 ar.serialize("bits", bits,
968 "lfo_active", lfo_active);
969
970 ar.serialize("state", state);
971 if (ar.versionBelow(version, 4)) {
972 assert(Archive::IS_LOADER);
973 if (state == one_of(EG_REV, EG_DMP)) {
974 state = EG_REL;
975 }
976 }
977
978 // Recalculate redundant state
979 if constexpr (Archive::IS_LOADER) {
980 step = calcStep(OCT, FN);
981 }
982
983 // This old comment is NOT completely true:
984 // Older version also had "env_vol_step" and "env_vol_lim" but those
985 // members were nowhere used, so removed those in the current
986 // version (it's ok to remove members from the savestate without
987 // updating the version number).
988 // When you remove member variables without increasing the version
989 // number, new openMSX executables can still read old savestates. And
990 // if you try to load a new savestate in an old openMSX version you do
991 // get a (cryptic) error message. But if the version number is
992 // increased the error message is much clearer.
993}
994
995// version 1: initial version
996// version 2: loadTime and busyTime moved to MSXMoonSound class
997// version 3: memAdr cannot be restored from register values
998// version 4: implement ram via Ram class
999template<typename Archive>
1000void YMF278::serialize(Archive& ar, unsigned version)
1001{
1002 ar.serialize("slots", slots,
1003 "eg_cnt", eg_cnt);
1004 if (ar.versionAtLeast(version, 4)) {
1005 ar.serialize("ram", ram);
1006 } else {
1007 ar.serialize_blob("ram", ram.getWriteBackdoor());
1008 }
1009 ar.serialize_blob("registers", regs);
1010 if (ar.versionAtLeast(version, 3)) { // must come after 'regs'
1011 ar.serialize("memadr", memAdr);
1012 } else {
1013 assert(Archive::IS_LOADER);
1014 // Old formats didn't store 'memAdr' so we also can't magically
1015 // restore the correct value. The best we can do is restore the
1016 // last set address.
1017 regs[3] &= 0x3F; // mask upper two bits
1018 memAdr = (regs[3] << 16) | (regs[4] << 8) | regs[5];
1019 }
1020
1021 // TODO restore more state from registers
1022 if constexpr (Archive::IS_LOADER) {
1023 for (auto [i, sl] : enumerate(slots)) {
1024 uint8_t t = regs[0x50 + i] >> 1;
1025 sl.TLdest = (t != 0x7f) ? t : 0xff;
1026
1027 sl.keyon = (regs[0x68 + i] & 0x80) != 0;
1028 sl.DAMP = (regs[0x68 + i] & 0x40) != 0;
1029 sl.lfo = (regs[0x80 + i] >> 3) & 7;
1030 }
1031 }
1032 // subclasses are responsible for calling setupMemoryPointers()
1033}
1035
1036
1037// class DebugRegisters
1038
1039YMF278::DebugRegisters::DebugRegisters(MSXMotherBoard& motherBoard_,
1040 const std::string& name_)
1041 : SimpleDebuggable(motherBoard_, name_ + " regs",
1042 "OPL4 registers", 0x100)
1043{
1044}
1045
1046uint8_t YMF278::DebugRegisters::read(unsigned address)
1047{
1048 const auto& ymf278 = OUTER(YMF278, debugRegisters);
1049 return ymf278.peekReg(narrow<uint8_t>(address));
1050}
1051
1052void YMF278::DebugRegisters::write(unsigned address, uint8_t value, EmuTime::param time)
1053{
1054 auto& ymf278 = OUTER(YMF278, debugRegisters);
1055 ymf278.writeReg(narrow<uint8_t>(address), value, time);
1056}
1057
1058
1059// class DebugMemory
1060
1061YMF278::DebugMemory::DebugMemory(MSXMotherBoard& motherBoard_,
1062 const std::string& name_)
1063 : SimpleDebuggable(motherBoard_, name_ + " mem",
1064 "OPL4 memory (includes both ROM and RAM)", 0x400000) // 4MB
1065{
1066}
1067
1068uint8_t YMF278::DebugMemory::read(unsigned address)
1069{
1070 const auto& ymf278 = OUTER(YMF278, debugMemory);
1071 return ymf278.readMem(address);
1072}
1073
1074void YMF278::DebugMemory::write(unsigned address, uint8_t value)
1075{
1076 auto& ymf278 = OUTER(YMF278, debugMemory);
1077 ymf278.writeMem(address, value);
1078}
1079
1080} // namespace openmsx
TclObject t
EmuTime::param getCurrentTime() const
Convenience method: This is the same as getScheduler().getCurrentTime().
auto size() const
Definition Rom.hh:37
void updateStream(EmuTime::param time)
void setSoftwareVolume(float volume, EmuTime::param time)
Change the 'software volume' of this sound device.
void unregisterSound()
Unregisters this sound device with the Mixer.
void registerSound(const DeviceConfig &config)
Registers this sound device with the Mixer.
void clear(byte c=0xff)
Definition TrackedRam.hh:46
void write(size_t addr, byte value)
Definition TrackedRam.hh:41
std::span< byte > getWriteBackdoor()
Definition TrackedRam.hh:55
size_t size() const
Definition TrackedRam.hh:20
YMF278(const std::string &name, size_t ramSize, const DeviceConfig &config, SetupMemPtrFunc setupMemPtrs_)
Definition YMF278.cc:796
uint8_t readReg(uint8_t reg)
Definition YMF278.cc:760
void writeReg(uint8_t reg, uint8_t data, EmuTime::param time)
Definition YMF278.cc:582
void setMixLevel(uint8_t x, EmuTime::param time)
Definition YMF278.cc:492
void reset(EmuTime::param time)
Definition YMF278.cc:830
void writeMem(unsigned address, uint8_t value)
Definition YMF278.cc:883
uint8_t readMem(unsigned address) const
Definition YMF278.cc:873
void clearRam()
Definition YMF278.cc:825
void setupMemoryPointers()
Definition YMF278.cc:867
std::function< void(bool, std::span< const uint8_t >, std::span< const uint8_t >, std::span< YMF278::Block128, 32 >)> SetupMemPtrFunc
Definition YMF278.hh:34
void serialize(Archive &ar, unsigned version)
Definition YMF278.cc:1000
uint8_t peekReg(uint8_t reg) const
Definition YMF278.cc:775
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
Definition enumerate.hh:28
This file implemented 3 utility functions:
Definition Autofire.cc:11
constexpr void fill(ForwardRange &&range, const T &value)
Definition ranges.hh:315
constexpr bool any_of(InputRange &&range, UnaryPredicate pred)
Definition ranges.hh:200
#define OUTER(type, member)
Definition outer.hh:42
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
#define UNREACHABLE
constexpr auto xrange(T e)
Definition xrange.hh:132