openMSX
YMF262.cc
Go to the documentation of this file.
1/*
2 *
3 * File: ymf262.c - software implementation of YMF262
4 * FM sound generator type OPL3
5 *
6 * Copyright (C) 2003 Jarek Burczynski
7 *
8 * Version 0.2
9 *
10 *
11 * Revision History:
12 *
13 * 03-03-2003: initial release
14 * - thanks to Olivier Galibert and Chris Hardy for YMF262 and YAC512 chips
15 * - thanks to Stiletto for the datasheets
16 *
17 *
18 *
19 * differences between OPL2 and OPL3 not documented in Yamaha datasheets:
20 * - sinus table is a little different: the negative part is off by one...
21 *
22 * - in order to enable selection of four different waveforms on OPL2
23 * one must set bit 5 in register 0x01(test).
24 * on OPL3 this bit is ignored and 4-waveform select works *always*.
25 * (Don't confuse this with OPL3's 8-waveform select.)
26 *
27 * - Envelope Generator: all 15 x rates take zero time on OPL3
28 * (on OPL2 15 0 and 15 1 rates take some time while 15 2 and 15 3 rates
29 * take zero time)
30 *
31 * - channel calculations: output of operator 1 is in perfect sync with
32 * output of operator 2 on OPL3; on OPL and OPL2 output of operator 1
33 * is always delayed by one sample compared to output of operator 2
34 *
35 *
36 * differences between OPL2 and OPL3 shown in datasheets:
37 * - YMF262 does not support CSM mode
38 */
39
40#include "YMF262.hh"
41#include "DeviceConfig.hh"
42#include "MSXMotherBoard.hh"
43#include "Math.hh"
44#include "cstd.hh"
45#include "narrow.hh"
46#include "outer.hh"
47#include "serialize.hh"
48#include "xrange.hh"
49#include <array>
50#include <cmath>
51#include <iostream>
52
53namespace openmsx {
54
55[[nodiscard]] static constexpr YMF262::FreqIndex fnumToIncrement(unsigned block_fnum)
56{
57 // opn phase increment counter = 20bit
58 // chip works with 10.10 fixed point, while we use 16.16
59 int block = narrow<int>((block_fnum & 0x1C00) >> 10);
60 return YMF262::FreqIndex(block_fnum & 0x03FF) >> (11 - block);
61}
62
63// envelope output entries
64static constexpr int ENV_BITS = 10;
65static constexpr int ENV_LEN = 1 << ENV_BITS;
66static constexpr double ENV_STEP = 128.0 / ENV_LEN;
67
68static constexpr int MAX_ATT_INDEX = (1 << (ENV_BITS - 1)) - 1; // 511
69static constexpr int MIN_ATT_INDEX = 0;
70
71static constexpr int TL_RES_LEN = 256; // 8 bits addressing (real chip)
72
73// register number to channel number , slot offset
74static constexpr uint8_t MOD = 0;
75static constexpr uint8_t CAR = 1;
76
77
78// mapping of register number (offset) to slot number used by the emulator
79static constexpr std::array<int, 32> slot_array = {
80 0, 2, 4, 1, 3, 5, -1, -1,
81 6, 8, 10, 7, 9, 11, -1, -1,
82 12, 14, 16, 13, 15, 17, -1, -1,
83 -1, -1, -1, -1, -1, -1, -1, -1
84};
85
86
87// key scale level
88// table is 3dB/octave , DV converts this into 6dB/octave
89// 0.1875 is bit 0 weight of the envelope counter (volume) expressed
90// in the 'decibel' scale
91[[nodiscard]] static constexpr int DV(double x) { return int(x / (0.1875 / 2.0)); }
92static constexpr std::array<unsigned, 8 * 16> ksl_tab = {
93 // OCT 0
94 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
95 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
96 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
97 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
98 // OCT 1
99 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
100 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
101 DV( 0.000), DV( 0.750), DV( 1.125), DV( 1.500),
102 DV( 1.875), DV( 2.250), DV( 2.625), DV( 3.000),
103 // OCT 2
104 DV( 0.000), DV( 0.000), DV( 0.000), DV( 0.000),
105 DV( 0.000), DV( 1.125), DV( 1.875), DV( 2.625),
106 DV( 3.000), DV( 3.750), DV( 4.125), DV( 4.500),
107 DV( 4.875), DV( 5.250), DV( 5.625), DV( 6.000),
108 // OCT 3
109 DV( 0.000), DV( 0.000), DV( 0.000), DV( 1.875),
110 DV( 3.000), DV( 4.125), DV( 4.875), DV( 5.625),
111 DV( 6.000), DV( 6.750), DV( 7.125), DV( 7.500),
112 DV( 7.875), DV( 8.250), DV( 8.625), DV( 9.000),
113 // OCT 4
114 DV( 0.000), DV( 0.000), DV( 3.000), DV( 4.875),
115 DV( 6.000), DV( 7.125), DV( 7.875), DV( 8.625),
116 DV( 9.000), DV( 9.750), DV(10.125), DV(10.500),
117 DV(10.875), DV(11.250), DV(11.625), DV(12.000),
118 // OCT 5
119 DV( 0.000), DV( 3.000), DV( 6.000), DV( 7.875),
120 DV( 9.000), DV(10.125), DV(10.875), DV(11.625),
121 DV(12.000), DV(12.750), DV(13.125), DV(13.500),
122 DV(13.875), DV(14.250), DV(14.625), DV(15.000),
123 // OCT 6
124 DV( 0.000), DV( 6.000), DV( 9.000), DV(10.875),
125 DV(12.000), DV(13.125), DV(13.875), DV(14.625),
126 DV(15.000), DV(15.750), DV(16.125), DV(16.500),
127 DV(16.875), DV(17.250), DV(17.625), DV(18.000),
128 // OCT 7
129 DV( 0.000), DV( 9.000), DV(12.000), DV(13.875),
130 DV(15.000), DV(16.125), DV(16.875), DV(17.625),
131 DV(18.000), DV(18.750), DV(19.125), DV(19.500),
132 DV(19.875), DV(20.250), DV(20.625), DV(21.000)
133};
134
135// sustain level table (3dB per step)
136// 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)
137[[nodiscard]] static constexpr int SC(int db) { return int(db * (2.0 / ENV_STEP)); }
138static constexpr std::array<int, 16> sl_tab = {
139 SC( 0), SC( 1), SC( 2), SC(3 ), SC(4 ), SC(5 ), SC(6 ), SC( 7),
140 SC( 8), SC( 9), SC(10), SC(11), SC(12), SC(13), SC(14), SC(31)
141};
142
143
144static constexpr uint8_t RATE_STEPS = 8;
145static constexpr std::array<uint8_t, 15 * RATE_STEPS> eg_inc = {
146//cycle:0 1 2 3 4 5 6 7
147 0,1, 0,1, 0,1, 0,1, // 0 rates 00..12 0 (increment by 0 or 1)
148 0,1, 0,1, 1,1, 0,1, // 1 rates 00..12 1
149 0,1, 1,1, 0,1, 1,1, // 2 rates 00..12 2
150 0,1, 1,1, 1,1, 1,1, // 3 rates 00..12 3
151
152 1,1, 1,1, 1,1, 1,1, // 4 rate 13 0 (increment by 1)
153 1,1, 1,2, 1,1, 1,2, // 5 rate 13 1
154 1,2, 1,2, 1,2, 1,2, // 6 rate 13 2
155 1,2, 2,2, 1,2, 2,2, // 7 rate 13 3
156
157 2,2, 2,2, 2,2, 2,2, // 8 rate 14 0 (increment by 2)
158 2,2, 2,4, 2,2, 2,4, // 9 rate 14 1
159 2,4, 2,4, 2,4, 2,4, // 10 rate 14 2
160 2,4, 4,4, 2,4, 4,4, // 11 rate 14 3
161
162 4,4, 4,4, 4,4, 4,4, // 12 rates 15 0, 15 1, 15 2, 15 3 for decay
163 8,8, 8,8, 8,8, 8,8, // 13 rates 15 0, 15 1, 15 2, 15 3 for attack (zero time)
164 0,0, 0,0, 0,0, 0,0, // 14 infinity rates for attack and decay(s)
165};
166
167
168// note that there is no O(13) in this table - it's directly in the code
169[[nodiscard]] static constexpr uint8_t O(int a) { return narrow<uint8_t>(a * RATE_STEPS); }
170static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_select = {
171 // Envelope Generator rates (16 + 64 rates + 16 RKS)
172 // 16 infinite time rates
173 O(14), O(14), O(14), O(14), O(14), O(14), O(14), O(14),
174 O(14), O(14), O(14), O(14), O(14), O(14), O(14), O(14),
175
176 // rates 00-12
177 O( 0), O( 1), O( 2), O( 3),
178 O( 0), O( 1), O( 2), O( 3),
179 O( 0), O( 1), O( 2), O( 3),
180 O( 0), O( 1), O( 2), O( 3),
181 O( 0), O( 1), O( 2), O( 3),
182 O( 0), O( 1), O( 2), O( 3),
183 O( 0), O( 1), O( 2), O( 3),
184 O( 0), O( 1), O( 2), O( 3),
185 O( 0), O( 1), O( 2), O( 3),
186 O( 0), O( 1), O( 2), O( 3),
187 O( 0), O( 1), O( 2), O( 3),
188 O( 0), O( 1), O( 2), O( 3),
189 O( 0), O( 1), O( 2), O( 3),
190
191 // rate 13
192 O( 4), O( 5), O( 6), O( 7),
193
194 // rate 14
195 O( 8), O( 9), O(10), O(11),
196
197 // rate 15
198 O(12), O(12), O(12), O(12),
199
200 // 16 dummy rates (same as 15 3)
201 O(12), O(12), O(12), O(12), O(12), O(12), O(12), O(12),
202 O(12), O(12), O(12), O(12), O(12), O(12), O(12), O(12),
203};
204
205// rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
206// shift 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
207// mask 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0
208static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_shift =
209{
210 // Envelope Generator counter shifts (16 + 64 rates + 16 RKS)
211 // 16 infinite time rates
212 0, 0, 0, 0, 0, 0, 0, 0,
213 0, 0, 0, 0, 0, 0, 0, 0,
214
215 // rates 00-15
216 12, 12, 12, 12,
217 11, 11, 11, 11,
218 10, 10, 10, 10,
219 9, 9, 9, 9,
220 8, 8, 8, 8,
221 7, 7, 7, 7,
222 6, 6, 6, 6,
223 5, 5, 5, 5,
224 4, 4, 4, 4,
225 3, 3, 3, 3,
226 2, 2, 2, 2,
227 1, 1, 1, 1,
228 0, 0, 0, 0,
229 0, 0, 0, 0,
230 0, 0, 0, 0,
231 0, 0, 0, 0,
232
233 // 16 dummy rates (same as 15 3)
234 0, 0, 0, 0, 0, 0, 0, 0,
235 0, 0, 0, 0, 0, 0, 0, 0,
236};
237
238
239// multiple table
240[[nodiscard]] static constexpr uint8_t ML(double x) { return uint8_t(2 * x); }
241static constexpr std::array<uint8_t, 16> mul_tab = {
242 // 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15
243 ML( 0.5), ML( 1.0), ML( 2.0), ML( 3.0),
244 ML( 4.0), ML( 5.0), ML( 6.0), ML( 7.0),
245 ML( 8.0), ML( 9.0), ML(10.0), ML(10.0),
246 ML(12.0), ML(12.0), ML(15.0), ML(15.0)
247};
248
249// LFO Amplitude Modulation table (verified on real YM3812)
250// 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples
251//
252// Length: 210 elements
253//
254// Each of the elements has to be repeated
255// exactly 64 times (on 64 consecutive samples).
256// The whole table takes: 64 * 210 = 13440 samples.
257//
258// When AM = 1 data is used directly
259// When AM = 0 data is divided by 4 before being used (loosing precision is important)
260
261static constexpr unsigned LFO_AM_TAB_ELEMENTS = 210;
262static constexpr std::array<uint8_t, LFO_AM_TAB_ELEMENTS> lfo_am_table = {
263 0, 0, 0,
264 0, 0, 0, 0,
265 1, 1, 1, 1,
266 2, 2, 2, 2,
267 3, 3, 3, 3,
268 4, 4, 4, 4,
269 5, 5, 5, 5,
270 6, 6, 6, 6,
271 7, 7, 7, 7,
272 8, 8, 8, 8,
273 9, 9, 9, 9,
274 10, 10, 10, 10,
275 11, 11, 11, 11,
276 12, 12, 12, 12,
277 13, 13, 13, 13,
278 14, 14, 14, 14,
279 15, 15, 15, 15,
280 16, 16, 16, 16,
281 17, 17, 17, 17,
282 18, 18, 18, 18,
283 19, 19, 19, 19,
284 20, 20, 20, 20,
285 21, 21, 21, 21,
286 22, 22, 22, 22,
287 23, 23, 23, 23,
288 24, 24, 24, 24,
289 25, 25, 25, 25,
290 26, 26, 26,
291 25, 25, 25, 25,
292 24, 24, 24, 24,
293 23, 23, 23, 23,
294 22, 22, 22, 22,
295 21, 21, 21, 21,
296 20, 20, 20, 20,
297 19, 19, 19, 19,
298 18, 18, 18, 18,
299 17, 17, 17, 17,
300 16, 16, 16, 16,
301 15, 15, 15, 15,
302 14, 14, 14, 14,
303 13, 13, 13, 13,
304 12, 12, 12, 12,
305 11, 11, 11, 11,
306 10, 10, 10, 10,
307 9, 9, 9, 9,
308 8, 8, 8, 8,
309 7, 7, 7, 7,
310 6, 6, 6, 6,
311 5, 5, 5, 5,
312 4, 4, 4, 4,
313 3, 3, 3, 3,
314 2, 2, 2, 2,
315 1, 1, 1, 1
316};
317
318// LFO Phase Modulation table (verified on real YM3812)
319static constexpr std::array<int8_t, 8 * 8 * 2> lfo_pm_table = {
320 // FNUM2/FNUM = 00 0xxxxxxx (0x0000)
321 0, 0, 0, 0, 0, 0, 0, 0, // LFO PM depth = 0
322 0, 0, 0, 0, 0, 0, 0, 0, // LFO PM depth = 1
323
324 // FNUM2/FNUM = 00 1xxxxxxx (0x0080)
325 0, 0, 0, 0, 0, 0, 0, 0, // LFO PM depth = 0
326 1, 0, 0, 0,-1, 0, 0, 0, // LFO PM depth = 1
327
328 // FNUM2/FNUM = 01 0xxxxxxx (0x0100)
329 1, 0, 0, 0,-1, 0, 0, 0, // LFO PM depth = 0
330 2, 1, 0,-1,-2,-1, 0, 1, // LFO PM depth = 1
331
332 // FNUM2/FNUM = 01 1xxxxxxx (0x0180)
333 1, 0, 0, 0,-1, 0, 0, 0, // LFO PM depth = 0
334 3, 1, 0,-1,-3,-1, 0, 1, // LFO PM depth = 1
335
336 // FNUM2/FNUM = 10 0xxxxxxx (0x0200)
337 2, 1, 0,-1,-2,-1, 0, 1, // LFO PM depth = 0
338 4, 2, 0,-2,-4,-2, 0, 2, // LFO PM depth = 1
339
340 // FNUM2/FNUM = 10 1xxxxxxx (0x0280)
341 2, 1, 0,-1,-2,-1, 0, 1, // LFO PM depth = 0
342 5, 2, 0,-2,-5,-2, 0, 2, // LFO PM depth = 1
343
344 // FNUM2/FNUM = 11 0xxxxxxx (0x0300)
345 3, 1, 0,-1,-3,-1, 0, 1, // LFO PM depth = 0
346 6, 3, 0,-3,-6,-3, 0, 3, // LFO PM depth = 1
347
348 // FNUM2/FNUM = 11 1xxxxxxx (0x0380)
349 3, 1, 0,-1,-3,-1, 0, 1, // LFO PM depth = 0
350 7, 3, 0,-3,-7,-3, 0, 3 // LFO PM depth = 1
351};
352
353// TL_TAB_LEN is calculated as:
354// (12+1)=13 - sinus amplitude bits (Y axis)
355// additional 1: to compensate for calculations of negative part of waveform
356// (if we don't add it then the greatest possible _negative_ value would be -2
357// and we really need -1 for waveform #7)
358// 2 - sinus sign bit (Y axis)
359// TL_RES_LEN - sinus resolution (X axis)
360static constexpr int TL_TAB_LEN = 13 * 2 * TL_RES_LEN;
361static constexpr int ENV_QUIET = TL_TAB_LEN >> 4;
362
363static constexpr auto tlTab = [] {
364 std::array<int, TL_TAB_LEN> result = {};
365 // this _is_ different from OPL2 (verified on real YMF262)
366 for (auto x : xrange(TL_RES_LEN)) {
367 double m = (1 << 16) / cstd::exp2<6>((x + 1) * (ENV_STEP / 4.0) / 8.0);
368
369 // we never reach (1<<16) here due to the (x+1)
370 // result fits within 16 bits at maximum
371 int n = int(m); // 16 bits here
372 n >>= 4; // 12 bits here
373 n = (n >> 1) + (n & 1); // round to nearest
374 // 11 bits here (rounded)
375 n <<= 1; // 12 bits here (as in real chip)
376 result[x * 2 + 0] = n;
377 result[x * 2 + 1] = ~result[x * 2 + 0];
378
379 for (int i : xrange(1, 13)) {
380 result[x * 2 + 0 + i * 2 * TL_RES_LEN] =
381 result[x * 2 + 0] >> i;
382 result[x * 2 + 1 + i * 2 * TL_RES_LEN] =
383 ~result[x * 2 + 0 + i * 2 * TL_RES_LEN];
384 }
385 }
386 return result;
387}();
388
389
390// sin waveform table in 'decibel' scale
391// there are eight waveforms on OPL3 chips
392struct SinTab {
393 std::array<std::array<unsigned, YMF262::SIN_LEN>, 8> tab;
394};
395
396static constexpr SinTab getSinTab()
397{
398 SinTab sin = {};
399
400 constexpr auto SIN_BITS = YMF262::SIN_BITS;
401 constexpr auto SIN_LEN = YMF262::SIN_LEN;
402 constexpr auto SIN_MASK = YMF262::SIN_MASK;
403 for (auto i : xrange(SIN_LEN / 4)) {
404 // non-standard sinus
405 double m = cstd::sin<2>(((i * 2) + 1) * Math::pi / SIN_LEN); // checked against the real chip
406 // we never reach zero here due to ((i * 2) + 1)
407 double o = -8.0 * cstd::log2<11, 3>(m); // convert to 'decibels'
408 o = o / (double(ENV_STEP) / 4);
409
410 int n = int(2 * o);
411 n = (n >> 1) + (n & 1); // round to nearest
412 sin.tab[0][i] = 2 * n;
413 }
414 for (auto i : xrange(SIN_LEN / 4)) {
415 sin.tab[0][SIN_LEN / 2 - 1 - i] = sin.tab[0][i];
416 }
417 for (auto i : xrange(SIN_LEN / 2)) {
418 sin.tab[0][SIN_LEN / 2 + i] = sin.tab[0][i] + 1;
419 }
420
421 for (auto i : xrange(SIN_LEN)) {
422 // these 'pictures' represent _two_ cycles
423 // waveform 1: __ __
424 // / \____/ \____
425 // output only first half of the sinus waveform (positive one)
426 sin.tab[1][i] = (i & (1 << (SIN_BITS - 1)))
427 ? TL_TAB_LEN
428 : sin.tab[0][i];
429
430 // waveform 2: __ __ __ __
431 // / \/ \/ \/ \.
432 // abs(sin)
433 sin.tab[2][i] = sin.tab[0][i & (SIN_MASK >> 1)];
434
435 // waveform 3: _ _ _ _
436 // / |_/ |_/ |_/ |_
437 // abs(output only first quarter of the sinus waveform)
438 sin.tab[3][i] = (i & (1 << (SIN_BITS - 2)))
439 ? TL_TAB_LEN
440 : sin.tab[0][i & (SIN_MASK>>2)];
441
442 // waveform 4: /\ ____/\ ____
443 // \/ \/
444 // output whole sinus waveform in half the cycle(step=2)
445 // and output 0 on the other half of cycle
446 sin.tab[4][i] = (i & (1 << (SIN_BITS - 1)))
447 ? TL_TAB_LEN
448 : sin.tab[0][i * 2];
449
450 // waveform 5: /\/\____/\/\____
451 //
452 // output abs(whole sinus) waveform in half the cycle(step=2)
453 // and output 0 on the other half of cycle
454 sin.tab[5][i] = (i & (1 << (SIN_BITS - 1)))
455 ? TL_TAB_LEN
456 : sin.tab[0][(i * 2) & (SIN_MASK >> 1)];
457
458 // waveform 6: ____ ____
459 // ____ ____
460 // output maximum in half the cycle and output minimum
461 // on the other half of cycle
462 sin.tab[6][i] = (i & (1 << (SIN_BITS - 1)))
463 ? 1 // negative
464 : 0; // positive
465
466 // waveform 7:|\____ |\____
467 // \| \|
468 // output sawtooth waveform
469 int x = (i & (1 << (SIN_BITS - 1)))
470 ? ((SIN_LEN - 1) - i) * 16 + 1 // negative: from 8177 to 1
471 : i * 16; // positive: from 0 to 8176
472 x = std::min(x, TL_TAB_LEN); // clip to the allowed range
473 sin.tab[7][i] = x;
474 }
475
476 return sin;
477}
478
479static constexpr SinTab sin = getSinTab();
480
481
482// TODO clean this up
483static int phase_modulation; // phase modulation input (SLOT 2)
484static int phase_modulation2; // phase modulation input (SLOT 3
485 // in 4 operator channels)
486
487
488YMF262::Slot::Slot()
489 : waveTable(sin.tab[0])
490{
491}
492
493
494void YMF262::callback(uint8_t flag)
495{
496 setStatus(flag);
497}
498
499// status set and IRQ handling
500void YMF262::setStatus(uint8_t flag)
501{
502 // set status flag masking out disabled IRQs
503 status |= flag;
504 if (status & statusMask) {
505 status |= 0x80;
506 irq.set();
507 }
508}
509
510// status reset and IRQ handling
511void YMF262::resetStatus(uint8_t flag)
512{
513 // reset status flag
514 status &= ~flag;
515 if (!(status & statusMask)) {
516 status &= 0x7F;
517 irq.reset();
518 }
519}
520
521// IRQ mask set
522void YMF262::changeStatusMask(uint8_t flag)
523{
524 statusMask = flag;
525 status &= statusMask;
526 if (status) {
527 status |= 0x80;
528 irq.set();
529 } else {
530 status &= 0x7F;
531 irq.reset();
532 }
533}
534
535void YMF262::Slot::advanceEnvelopeGenerator(unsigned egCnt)
536{
537 switch (state) {
538 case EG_ATTACK:
539 if (!(egCnt & eg_m_ar)) {
540 volume += (~volume * eg_inc[eg_sel_ar + ((egCnt >> eg_sh_ar) & 7)]) >> 3;
541 if (volume <= MIN_ATT_INDEX) {
542 volume = MIN_ATT_INDEX;
543 state = EG_DECAY;
544 }
545 }
546 break;
547
548 case EG_DECAY:
549 if (!(egCnt & eg_m_dr)) {
550 volume += eg_inc[eg_sel_dr + ((egCnt >> eg_sh_dr) & 7)];
551 if (volume >= sl) {
552 state = EG_SUSTAIN;
553 }
554 }
555 break;
556
557 case EG_SUSTAIN:
558 // this is important behaviour:
559 // one can change percussive/non-percussive
560 // modes on the fly and the chip will remain
561 // in sustain phase - verified on real YM3812
562 if (eg_type) {
563 // non-percussive mode
564 // do nothing
565 } else {
566 // percussive mode
567 // during sustain phase chip adds Release Rate (in percussive mode)
568 if (!(egCnt & eg_m_rr)) {
569 volume += eg_inc[eg_sel_rr + ((egCnt >> eg_sh_rr) & 7)];
570 if (volume >= MAX_ATT_INDEX) {
571 volume = MAX_ATT_INDEX;
572 }
573 } else {
574 // do nothing in sustain phase
575 }
576 }
577 break;
578
579 case EG_RELEASE:
580 if (!(egCnt & eg_m_rr)) {
581 volume += eg_inc[eg_sel_rr + ((egCnt >> eg_sh_rr) & 7)];
582 if (volume >= MAX_ATT_INDEX) {
583 volume = MAX_ATT_INDEX;
584 state = EG_OFF;
585 }
586 }
587 break;
588
589 default:
590 break;
591 }
592}
593
594void YMF262::Slot::advancePhaseGenerator(Channel& ch, unsigned lfo_pm)
595{
596 if (vib) {
597 // LFO phase modulation active
598 unsigned block_fnum = ch.block_fnum;
599 unsigned fnum_lfo = (block_fnum & 0x0380) >> 7;
600 auto lfo_fn_table_index_offset = narrow_cast<int>(lfo_pm_table[lfo_pm + 16 * fnum_lfo]);
601 Cnt += fnumToIncrement(block_fnum + lfo_fn_table_index_offset) * mul;
602 } else {
603 // LFO phase modulation disabled for this operator
604 Cnt += Incr;
605 }
606}
607
608// advance to next sample
609void YMF262::advance()
610{
611 // Vibrato: 8 output levels (triangle waveform);
612 // 1 level takes 1024 samples
613 lfo_pm_cnt.addQuantum();
614 unsigned lfo_pm = (lfo_pm_cnt.toInt() & 7) | lfo_pm_depth_range;
615
616 ++eg_cnt;
617 for (auto& ch : channel) {
618 for (auto& op : ch.slot) {
619 op.advanceEnvelopeGenerator(eg_cnt);
620 op.advancePhaseGenerator(ch, lfo_pm);
621 }
622 }
623
624 // The Noise Generator of the YM3812 is 23-bit shift register.
625 // Period is equal to 2^23-2 samples.
626 // Register works at sampling frequency of the chip, so output
627 // can change on every sample.
628 //
629 // Output of the register and input to the bit 22 is:
630 // bit0 XOR bit14 XOR bit15 XOR bit22
631 //
632 // Simply use bit 22 as the noise output.
633 //
634 // unsigned j = ((noise_rng >> 0) ^ (noise_rng >> 14) ^
635 // (noise_rng >> 15) ^ (noise_rng >> 22)) & 1;
636 // noise_rng = (j << 22) | (noise_rng >> 1);
637 //
638 // Instead of doing all the logic operations above, we
639 // use a trick here (and use bit 0 as the noise output).
640 // The difference is only that the noise bit changes one
641 // step ahead. This doesn't matter since we don't know
642 // what is real state of the noise_rng after the reset.
643 if (noise_rng & 1) {
644 noise_rng ^= 0x800302;
645 }
646 noise_rng >>= 1;
647}
648
649inline int YMF262::Slot::op_calc(unsigned phase, unsigned lfo_am) const
650{
651 unsigned env = (TLL + volume + (lfo_am & AMmask)) << 4;
652 auto p = env + waveTable[phase & SIN_MASK];
653 return (p < TL_TAB_LEN) ? tlTab[p] : 0;
654}
655
656// calculate output of a standard 2 operator channel
657// (or 1st part of a 4-op channel)
658void YMF262::Channel::chan_calc(unsigned lfo_am)
659{
660 // !! something is wrong with this, it caused bug
661 // !! [2823673] MoonSound 4 operator FM fail
662 // !! optimization disabled for now
663 // !! TODO investigate
664 // !! maybe this micro optimization isn't worth the trouble/risk
665 // !!
666 // - mod.connect can point to 'phase_modulation' or 'ch0-output'
667 // - car.connect can point to 'phase_modulation2' or 'ch0-output'
668 // (see register #C0-#C8 writes)
669 // - phase_modulation2 is only used in 4op mode
670 // - mod.connect and car.connect can point to the same thing, so we need
671 // an addition for car.connect (and initialize phase_modulation2 to
672 // zero). For mod.connect we can directly assign the value.
673
674 // ?? is this paragraph correct ??
675 // phase_modulation should be initialized to zero here. But there seems
676 // to be an optimization bug in gcc-4.2: it *seems* that when we
677 // initialize phase_modulation to zero in this function, the optimizer
678 // assumes it still has value zero at the end of this function (where
679 // it's used to calculate car.connect). As a workaround we initialize
680 // phase_modulation each time before calling this function.
681 phase_modulation = 0;
682 phase_modulation2 = 0;
683
684 auto& mod = slot[MOD];
685 int out = mod.fb_shift
686 ? mod.op1_out[0] + mod.op1_out[1]
687 : 0;
688 mod.op1_out[0] = mod.op1_out[1];
689 mod.op1_out[1] = mod.op_calc(mod.Cnt.toInt() + (out >> mod.fb_shift), lfo_am);
690 *mod.connect += mod.op1_out[1];
691
692 auto& car = slot[CAR];
693 *car.connect += car.op_calc(car.Cnt.toInt() + phase_modulation, lfo_am);
694}
695
696// calculate output of a 2nd part of 4-op channel
697void YMF262::Channel::chan_calc_ext(unsigned lfo_am)
698{
699 // !! see remark in chan_cal(), something is wrong with this
700 // !! optimization disabled for now
701 // !!
702 // - mod.connect can point to 'phase_modulation' or 'ch3-output'
703 // - car.connect always points to 'ch3-output' (always 4op-mode)
704 // (see register #C0-#C8 writes)
705 // - mod.connect and car.connect can point to the same thing, so we need
706 // an addition for car.connect. For mod.connect we can directly assign
707 // the value.
708
709 phase_modulation = 0;
710
711 auto& mod = slot[MOD];
712 *mod.connect += mod.op_calc(mod.Cnt.toInt() + phase_modulation2, lfo_am);
713
714 auto& car = slot[CAR];
715 *car.connect += car.op_calc(car.Cnt.toInt() + phase_modulation, lfo_am);
716}
717
718// operators used in the rhythm sounds generation process:
719//
720// Envelope Generator:
721//
722// channel operator register number Bass High Snare Tom Top
723// / slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal
724// 6 / 0 12 50 70 90 f0 +
725// 6 / 1 15 53 73 93 f3 +
726// 7 / 0 13 51 71 91 f1 +
727// 7 / 1 16 54 74 94 f4 +
728// 8 / 0 14 52 72 92 f2 +
729// 8 / 1 17 55 75 95 f5 +
730//
731// Phase Generator:
732//
733// channel operator register number Bass High Snare Tom Top
734// / slot number MULTIPLE Drum Hat Drum Tom Cymbal
735// 6 / 0 12 30 +
736// 6 / 1 15 33 +
737// 7 / 0 13 31 + + +
738// 7 / 1 16 34 ----- n o t u s e d -----
739// 8 / 0 14 32 +
740// 8 / 1 17 35 + +
741//
742// channel operator register number Bass High Snare Tom Top
743// number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
744// 6 12,15 B6 A6 +
745//
746// 7 13,16 B7 A7 + + +
747//
748// 8 14,17 B8 A8 + + +
749
750// The following formulas can be well optimized.
751// I leave them in direct form for now (in case I've missed something).
752
753inline unsigned YMF262::genPhaseHighHat()
754{
755 // high hat phase generation (verified on real YM3812):
756 // phase = d0 or 234 (based on frequency only)
757 // phase = 34 or 2d0 (based on noise)
758
759 // base frequency derived from operator 1 in channel 7
760 int op71phase = channel[7].slot[MOD].Cnt.toInt();
761 bool bit7 = (op71phase & 0x80) != 0;
762 bool bit3 = (op71phase & 0x08) != 0;
763 bool bit2 = (op71phase & 0x04) != 0;
764 bool res1 = (bit2 ^ bit7) | bit3;
765 // when res1 = 0 phase = 0x000 | 0xd0;
766 // when res1 = 1 phase = 0x200 | (0xd0>>2);
767 unsigned phase = res1 ? (0x200 | (0xd0 >> 2)) : 0xd0;
768
769 // enable gate based on frequency of operator 2 in channel 8
770 int op82phase = channel[8].slot[CAR].Cnt.toInt();
771 bool bit5e= (op82phase & 0x20) != 0;
772 bool bit3e= (op82phase & 0x08) != 0;
773 bool res2 = (bit3e ^ bit5e);
774 // when res2 = 0 pass the phase from calculation above (res1);
775 // when res2 = 1 phase = 0x200 | (0xd0>>2);
776 if (res2) {
777 phase = (0x200 | (0xd0 >> 2));
778 }
779
780 // when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0
781 // when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change
782 if (phase & 0x200) {
783 if (noise_rng & 1) {
784 phase = 0x200 | 0xd0;
785 }
786 } else {
787 // when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2
788 // when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change
789 if (noise_rng & 1) {
790 phase = 0xd0 >> 2;
791 }
792 }
793 return phase;
794}
795
796inline unsigned YMF262::genPhaseSnare()
797{
798 // verified on real YM3812
799 // base frequency derived from operator 1 in channel 7
800 // noise bit XOR'es phase by 0x100
801 return ((channel[7].slot[MOD].Cnt.toInt() & 0x100) + 0x100)
802 ^ ((noise_rng & 1) << 8);
803}
804
805inline unsigned YMF262::genPhaseCymbal()
806{
807 // verified on real YM3812
808 // enable gate based on frequency of operator 2 in channel 8
809 // NOTE: YM2413_2 uses bit5 | bit3, this core uses bit5 ^ bit3
810 // most likely only one of the two is correct
811 int op82phase = channel[8].slot[CAR].Cnt.toInt();
812 if ((op82phase ^ (op82phase << 2)) & 0x20) { // bit5 ^ bit3
813 return 0x300;
814 } else {
815 // base frequency derived from operator 1 in channel 7
816 int op71phase = channel[7].slot[MOD].Cnt.toInt();
817 bool bit7 = (op71phase & 0x80) != 0;
818 bool bit3 = (op71phase & 0x08) != 0;
819 bool bit2 = (op71phase & 0x04) != 0;
820 return ((bit2 != bit7) || bit3) ? 0x300 : 0x100;
821 }
822}
823
824// calculate rhythm
825void YMF262::chan_calc_rhythm(unsigned lfo_am)
826{
827 // Bass Drum (verified on real YM3812):
828 // - depends on the channel 6 'connect' register:
829 // when connect = 0 it works the same as in normal (non-rhythm)
830 // mode (op1->op2->out)
831 // when connect = 1 _only_ operator 2 is present on output
832 // (op2->out), operator 1 is ignored
833 // - output sample always is multiplied by 2
834 auto& mod6 = channel[6].slot[MOD];
835 int out = mod6.fb_shift ? mod6.op1_out[0] + mod6.op1_out[1] : 0;
836 mod6.op1_out[0] = mod6.op1_out[1];
837 int pm = mod6.CON ? 0 : mod6.op1_out[0];
838 mod6.op1_out[1] = mod6.op_calc(mod6.Cnt.toInt() + (out >> mod6.fb_shift), lfo_am);
839 auto& car6 = channel[6].slot[CAR];
840 chanOut[6] += 2 * car6.op_calc(car6.Cnt.toInt() + pm, lfo_am);
841
842 // Phase generation is based on:
843 // HH (13) channel 7->slot 1 combined with channel 8->slot 2
844 // (same combination as TOP CYMBAL but different output phases)
845 // SD (16) channel 7->slot 1
846 // TOM (14) channel 8->slot 1
847 // TOP (17) channel 7->slot 1 combined with channel 8->slot 2
848 // (same combination as HIGH HAT but different output phases)
849 //
850 // Envelope generation based on:
851 // HH channel 7->slot1
852 // SD channel 7->slot2
853 // TOM channel 8->slot1
854 // TOP channel 8->slot2
855 auto& mod7 = channel[7].slot[MOD];
856 chanOut[7] += 2 * mod7.op_calc(genPhaseHighHat(), lfo_am);
857 auto& car7 = channel[7].slot[CAR];
858 chanOut[7] += 2 * car7.op_calc(genPhaseSnare(), lfo_am);
859 auto& mod8 = channel[8].slot[MOD];
860 chanOut[8] += 2 * mod8.op_calc(mod8.Cnt.toInt(), lfo_am);
861 auto& car8 = channel[8].slot[CAR];
862 chanOut[8] += 2 * car8.op_calc(genPhaseCymbal(), lfo_am);
863}
864
865void YMF262::Slot::FM_KEYON(uint8_t key_set)
866{
867 if (!key) {
868 // restart Phase Generator
869 Cnt = FreqIndex(0);
870 // phase -> Attack
871 state = EG_ATTACK;
872 }
873 key |= key_set;
874}
875
876void YMF262::Slot::FM_KEYOFF(uint8_t key_clr)
877{
878 if (key) {
879 key &= ~key_clr;
880 if (!key) {
881 // phase -> Release
882 if (state != EG_OFF) {
883 state = EG_RELEASE;
884 }
885 }
886 }
887}
888
889void YMF262::Slot::update_ar_dr()
890{
891 if ((ar + ksr) < 16 + 60) {
892 // verified on real YMF262 - all 15 x rates take "zero" time
893 eg_sh_ar = eg_rate_shift [ar + ksr];
894 eg_sel_ar = eg_rate_select[ar + ksr];
895 } else {
896 eg_sh_ar = 0;
897 eg_sel_ar = 13 * RATE_STEPS;
898 }
899 eg_m_ar = (1 << eg_sh_ar) - 1;
900 eg_sh_dr = eg_rate_shift [dr + ksr];
901 eg_sel_dr = eg_rate_select[dr + ksr];
902 eg_m_dr = (1 << eg_sh_dr) - 1;
903}
904void YMF262::Slot::update_rr()
905{
906 eg_sh_rr = eg_rate_shift [rr + ksr];
907 eg_sel_rr = eg_rate_select[rr + ksr];
908 eg_m_rr = (1 << eg_sh_rr) - 1;
909}
910
911// update phase increment counter of operator (also update the EG rates if necessary)
912void YMF262::Slot::calc_fc(const Channel& ch)
913{
914 // (frequency) phase increment counter
915 Incr = ch.fc * mul;
916
917 auto newKsr = narrow<uint8_t>(ch.kcode >> KSR);
918 if (ksr == newKsr) return;
919 ksr = newKsr;
920
921 // calculate envelope generator rates
922 update_ar_dr();
923 update_rr();
924}
925
926static constexpr std::array<unsigned, 18> channelPairTab = {
927 0, 1, 2, 0, 1, 2, unsigned(~0), unsigned(~0), unsigned(~0),
928 9, 10, 11, 9, 10, 11, unsigned(~0), unsigned(~0), unsigned(~0),
929};
930inline bool YMF262::isExtended(unsigned ch) const
931{
932 assert(ch < 18);
933 if (!OPL3_mode) return false;
934 if (channelPairTab[ch] == unsigned(~0)) return false;
935 return channel[channelPairTab[ch]].extended;
936}
937static constexpr unsigned getFirstOfPairNum(unsigned ch)
938{
939 assert((ch < 18) && (channelPairTab[ch] != unsigned(~0)));
940 return channelPairTab[ch];
941}
942inline YMF262::Channel& YMF262::getFirstOfPair(unsigned ch)
943{
944 return channel[getFirstOfPairNum(ch) + 0];
945}
946inline YMF262::Channel& YMF262::getSecondOfPair(unsigned ch)
947{
948 return channel[getFirstOfPairNum(ch) + 3];
949}
950
951// set multi,am,vib,EG-TYP,KSR,mul
952void YMF262::set_mul(unsigned sl, uint8_t v)
953{
954 unsigned chan_no = sl / 2;
955 auto& ch = channel[chan_no];
956 auto& slot = ch.slot[sl & 1];
957
958 slot.mul = mul_tab[v & 0x0f];
959 slot.KSR = (v & 0x10) ? 0 : 2;
960 slot.eg_type = (v & 0x20) != 0;
961 slot.vib = (v & 0x40) != 0;
962 slot.AMmask = (v & 0x80) ? ~0 : 0;
963
964 if (isExtended(chan_no)) {
965 // 4op mode
966 // update this slot using frequency data for 1st channel of a pair
967 slot.calc_fc(getFirstOfPair(chan_no));
968 } else {
969 // normal (OPL2 mode or 2op mode)
970 slot.calc_fc(ch);
971 }
972}
973
974// set ksl & tl
975void YMF262::set_ksl_tl(unsigned sl, uint8_t v)
976{
977 unsigned chan_no = sl / 2;
978 auto& ch = channel[chan_no];
979 auto& slot = ch.slot[sl & 1];
980
981 // This is indeed {0.0, 3.0, 1.5, 6.0} dB/oct, verified on real YMF262.
982 // Note the illogical order of 2nd and 3rd element.
983 static constexpr std::array<uint8_t, 4> ksl_shift = {31, 1, 2, 0};
984 slot.ksl = ksl_shift[v >> 6];
985
986 slot.TL = (v & 0x3F) << (ENV_BITS - 1 - 7); // 7 bits TL (bit 6 = always 0)
987
988 if (isExtended(chan_no)) {
989 // update this slot using frequency data for 1st channel of a pair
990 auto& ch0 = getFirstOfPair(chan_no);
991 slot.TLL = slot.TL + (ch0.ksl_base >> slot.ksl);
992 } else {
993 // normal
994 slot.TLL = slot.TL + (ch.ksl_base >> slot.ksl);
995 }
996}
997
998// set attack rate & decay rate
999void YMF262::set_ar_dr(unsigned sl, uint8_t v)
1000{
1001 auto& ch = channel[sl / 2];
1002 auto& slot = ch.slot[sl & 1];
1003
1004 slot.ar = (v >> 4) ? narrow<uint8_t>(16 + ((v >> 4) << 2)) : 0;
1005 slot.dr = (v & 0x0F) ? narrow<uint8_t>(16 + ((v & 0x0F) << 2)) : 0;
1006 slot.update_ar_dr();
1007}
1008
1009// set sustain level & release rate
1010void YMF262::set_sl_rr(unsigned sl, uint8_t v)
1011{
1012 auto& ch = channel[sl / 2];
1013 auto& slot = ch.slot[sl & 1];
1014
1015 slot.sl = sl_tab[v >> 4];
1016 slot.rr = (v & 0x0F) ? uint8_t(16 + ((v & 0x0F) << 2)) : 0;
1017 slot.update_rr();
1018}
1019
1020uint8_t YMF262::readReg(unsigned r)
1021{
1022 // no need to call updateStream(time)
1023 return peekReg(r);
1024}
1025
1026uint8_t YMF262::peekReg(unsigned r) const
1027{
1028 return reg[r];
1029}
1030
1031void YMF262::writeReg(unsigned r, uint8_t v, EmuTime::param time)
1032{
1033 if (!OPL3_mode && (r != 0x105)) {
1034 // in OPL2 mode the only accessible in set #2 is register 0x05
1035 r &= ~0x100;
1036 }
1037 writeReg512(r, v, time);
1038}
1039void YMF262::writeReg512(unsigned r, uint8_t v, EmuTime::param time)
1040{
1041 updateStream(time); // TODO optimize only for regs that directly influence sound
1042 writeRegDirect(r, v, time);
1043}
1044void YMF262::writeRegDirect(unsigned r, uint8_t v, EmuTime::param time)
1045{
1046 reg[r] = v;
1047
1048 switch (r) {
1049 case 0x104:
1050 // 6 channels enable
1051 channel[ 0].extended = (v & 0x01) != 0;
1052 channel[ 1].extended = (v & 0x02) != 0;
1053 channel[ 2].extended = (v & 0x04) != 0;
1054 channel[ 9].extended = (v & 0x08) != 0;
1055 channel[10].extended = (v & 0x10) != 0;
1056 channel[11].extended = (v & 0x20) != 0;
1057 return;
1058
1059 case 0x105:
1060 // OPL3 mode when bit0=1 otherwise it is OPL2 mode
1061 OPL3_mode = v & 0x01;
1062
1063 // Verified on real YMF278: When NEW2 bit is first set, a read
1064 // from the status register (once) returns bit 1 set (0x02).
1065 // This only happens once after reset, so clearing NEW2 and
1066 // setting it again doesn't cause another change in the status
1067 // register. Also, only bit 1 changes.
1068 if ((v & 0x02) && !alreadySignaledNEW2 && isYMF278) {
1069 status2 = 0x02;
1070 alreadySignaledNEW2 = true;
1071 }
1072
1073 // following behaviour was tested on real YMF262,
1074 // switching OPL3/OPL2 modes on the fly:
1075 // - does not change the waveform previously selected
1076 // (unless when ....)
1077 // - does not update CH.A, CH.B, CH.C and CH.D output
1078 // selectors (registers c0-c8) (unless when ....)
1079 // - does not disable channels 9-17 on OPL3->OPL2 switch
1080 // - does not switch 4 operator channels back to 2
1081 // operator channels
1082 return;
1083 }
1084
1085 unsigned ch_offset = (r & 0x100) ? 9 : 0;
1086 switch (r & 0xE0) {
1087 case 0x00: // 00-1F:control
1088 switch (r & 0x1F) {
1089 case 0x01: // test register
1090 break;
1091
1092 case 0x02: // Timer 1
1093 timer1->setValue(v);
1094 break;
1095
1096 case 0x03: // Timer 2
1097 timer2->setValue(v);
1098 break;
1099
1100 case 0x04: // IRQ clear / mask and Timer enable
1101 if (v & 0x80) {
1102 // IRQ flags clear
1103 resetStatus(0x60);
1104 } else {
1105 changeStatusMask((~v) & 0x60);
1106 timer1->setStart((v & R04_ST1) != 0, time);
1107 timer2->setStart((v & R04_ST2) != 0, time);
1108 }
1109 break;
1110
1111 case 0x08: // x,NTS,x,x, x,x,x,x
1112 nts = (v & 0x40) != 0;
1113 break;
1114
1115 default:
1116 break;
1117 }
1118 break;
1119
1120 case 0x20: { // am ON, vib ON, ksr, eg_type, mul
1121 int slot = slot_array[r & 0x1F];
1122 if (slot < 0) return;
1123 set_mul(slot + ch_offset * 2, v);
1124 break;
1125 }
1126 case 0x40: {
1127 int slot = slot_array[r & 0x1F];
1128 if (slot < 0) return;
1129 set_ksl_tl(slot + ch_offset * 2, v);
1130 break;
1131 }
1132 case 0x60: {
1133 int slot = slot_array[r & 0x1F];
1134 if (slot < 0) return;
1135 set_ar_dr(slot + ch_offset * 2, v);
1136 break;
1137 }
1138 case 0x80: {
1139 int slot = slot_array[r & 0x1F];
1140 if (slot < 0) return;
1141 set_sl_rr(slot + ch_offset * 2, v);
1142 break;
1143 }
1144 case 0xA0: {
1145 // note: not r != 0x1BD, only first register block
1146 if (r == 0xBD) {
1147 // am depth, vibrato depth, r,bd,sd,tom,tc,hh
1148 lfo_am_depth = (v & 0x80) != 0;
1149 lfo_pm_depth_range = (v & 0x40) ? 8 : 0;
1150 rhythm = v & 0x3F;
1151
1152 if (rhythm & 0x20) {
1153 // BD key on/off
1154 if (v & 0x10) {
1155 channel[6].slot[MOD].FM_KEYON (2);
1156 channel[6].slot[CAR].FM_KEYON (2);
1157 } else {
1158 channel[6].slot[MOD].FM_KEYOFF(2);
1159 channel[6].slot[CAR].FM_KEYOFF(2);
1160 }
1161 // HH key on/off
1162 if (v & 0x01) {
1163 channel[7].slot[MOD].FM_KEYON (2);
1164 } else {
1165 channel[7].slot[MOD].FM_KEYOFF(2);
1166 }
1167 // SD key on/off
1168 if (v & 0x08) {
1169 channel[7].slot[CAR].FM_KEYON (2);
1170 } else {
1171 channel[7].slot[CAR].FM_KEYOFF(2);
1172 }
1173 // TOM key on/off
1174 if (v & 0x04) {
1175 channel[8].slot[MOD].FM_KEYON (2);
1176 } else {
1177 channel[8].slot[MOD].FM_KEYOFF(2);
1178 }
1179 // TOP-CY key on/off
1180 if (v & 0x02) {
1181 channel[8].slot[CAR].FM_KEYON (2);
1182 } else {
1183 channel[8].slot[CAR].FM_KEYOFF(2);
1184 }
1185 } else {
1186 // BD key off
1187 channel[6].slot[MOD].FM_KEYOFF(2);
1188 channel[6].slot[CAR].FM_KEYOFF(2);
1189 // HH key off
1190 channel[7].slot[MOD].FM_KEYOFF(2);
1191 // SD key off
1192 channel[7].slot[CAR].FM_KEYOFF(2);
1193 // TOM key off
1194 channel[8].slot[MOD].FM_KEYOFF(2);
1195 // TOP-CY off
1196 channel[8].slot[CAR].FM_KEYOFF(2);
1197 }
1198 return;
1199 }
1200
1201 // keyon,block,fnum
1202 if ((r & 0x0F) > 8) {
1203 return;
1204 }
1205 unsigned chan_no = (r & 0x0F) + ch_offset;
1206 auto& ch = channel[chan_no];
1207 int block_fnum;
1208 if (!(r & 0x10)) {
1209 // a0-a8
1210 block_fnum = (ch.block_fnum & 0x1F00) | v;
1211 } else {
1212 // b0-b8
1213 block_fnum = ((v & 0x1F) << 8) | (ch.block_fnum & 0xFF);
1214 if (isExtended(chan_no)) {
1215 if (getFirstOfPairNum(chan_no) == chan_no) {
1216 // keyon/off slots of both channels
1217 // forming a 4-op channel
1218 auto& ch0 = getFirstOfPair(chan_no);
1219 auto& ch3 = getSecondOfPair(chan_no);
1220 if (v & 0x20) {
1221 ch0.slot[MOD].FM_KEYON(1);
1222 ch0.slot[CAR].FM_KEYON(1);
1223 ch3.slot[MOD].FM_KEYON(1);
1224 ch3.slot[CAR].FM_KEYON(1);
1225 } else {
1226 ch0.slot[MOD].FM_KEYOFF(1);
1227 ch0.slot[CAR].FM_KEYOFF(1);
1228 ch3.slot[MOD].FM_KEYOFF(1);
1229 ch3.slot[CAR].FM_KEYOFF(1);
1230 }
1231 } else {
1232 // do nothing
1233 }
1234 } else {
1235 // 2 operator function keyon/off
1236 if (v & 0x20) {
1237 ch.slot[MOD].FM_KEYON (1);
1238 ch.slot[CAR].FM_KEYON (1);
1239 } else {
1240 ch.slot[MOD].FM_KEYOFF(1);
1241 ch.slot[CAR].FM_KEYOFF(1);
1242 }
1243 }
1244 }
1245 // update
1246 if (ch.block_fnum != block_fnum) {
1247 ch.block_fnum = block_fnum;
1248 ch.ksl_base = ksl_tab[block_fnum >> 6];
1249 ch.fc = fnumToIncrement(block_fnum);
1250
1251 // BLK 2,1,0 bits -> bits 3,2,1 of kcode
1252 ch.kcode = (ch.block_fnum & 0x1C00) >> 9;
1253
1254 // the info below is actually opposite to what is stated
1255 // in the Manuals (verified on real YMF262)
1256 // if noteSel == 0 -> lsb of kcode is bit 10 (MSB) of fnum
1257 // if noteSel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum
1258 if (nts) {
1259 ch.kcode |= (ch.block_fnum & 0x100) >> 8; // noteSel == 1
1260 } else {
1261 ch.kcode |= (ch.block_fnum & 0x200) >> 9; // noteSel == 0
1262 }
1263 if (isExtended(chan_no)) {
1264 if (getFirstOfPairNum(chan_no) == chan_no) {
1265 // update slots of both channels
1266 // forming up 4-op channel
1267 // refresh Total Level
1268 auto& ch0 = getFirstOfPair(chan_no);
1269 auto& ch3 = getSecondOfPair(chan_no);
1270 ch0.slot[MOD].TLL = ch0.slot[MOD].TL + (ch.ksl_base >> ch0.slot[MOD].ksl);
1271 ch0.slot[CAR].TLL = ch0.slot[CAR].TL + (ch.ksl_base >> ch0.slot[CAR].ksl);
1272 ch3.slot[MOD].TLL = ch3.slot[MOD].TL + (ch.ksl_base >> ch3.slot[MOD].ksl);
1273 ch3.slot[CAR].TLL = ch3.slot[CAR].TL + (ch.ksl_base >> ch3.slot[CAR].ksl);
1274
1275 // refresh frequency counter
1276 ch0.slot[MOD].calc_fc(ch);
1277 ch0.slot[CAR].calc_fc(ch);
1278 ch3.slot[MOD].calc_fc(ch);
1279 ch3.slot[CAR].calc_fc(ch);
1280 } else {
1281 // nothing
1282 }
1283 } else {
1284 // refresh Total Level in both SLOTs of this channel
1285 ch.slot[MOD].TLL = ch.slot[MOD].TL + (ch.ksl_base >> ch.slot[MOD].ksl);
1286 ch.slot[CAR].TLL = ch.slot[CAR].TL + (ch.ksl_base >> ch.slot[CAR].ksl);
1287
1288 // refresh frequency counter in both SLOTs of this channel
1289 ch.slot[MOD].calc_fc(ch);
1290 ch.slot[CAR].calc_fc(ch);
1291 }
1292 }
1293 break;
1294 }
1295 case 0xC0: {
1296 // CH.D, CH.C, CH.B, CH.A, FB(3bits), C
1297 if ((r & 0xF) > 8) {
1298 return;
1299 }
1300 unsigned chan_no = (r & 0x0F) + ch_offset;
1301 auto& ch = channel[chan_no];
1302
1303 unsigned base = chan_no * 4;
1304 if (OPL3_mode) {
1305 // OPL3 mode
1306 pan[base + 0] = (v & 0x10) ? ~0 : 0; // ch.A
1307 pan[base + 1] = (v & 0x20) ? ~0 : 0; // ch.B
1308 pan[base + 2] = (v & 0x40) ? ~0 : 0; // ch.C
1309 pan[base + 3] = (v & 0x80) ? ~0 : 0; // ch.D
1310 } else {
1311 // OPL2 mode - always enabled
1312 pan[base + 0] = ~0; // ch.A
1313 pan[base + 1] = ~0; // ch.B
1314 pan[base + 2] = ~0; // ch.C
1315 pan[base + 3] = ~0; // ch.D
1316 }
1317
1318 ch.slot[MOD].setFeedbackShift((v >> 1) & 7);
1319 ch.slot[MOD].CON = v & 1;
1320
1321 if (isExtended(chan_no)) {
1322 unsigned chan_no0 = getFirstOfPairNum(chan_no);
1323 unsigned chan_no3 = chan_no0 + 3;
1324 auto& ch0 = getFirstOfPair(chan_no);
1325 auto& ch3 = getSecondOfPair(chan_no);
1326 switch ((ch0.slot[MOD].CON ? 2:0) | (ch3.slot[MOD].CON ? 1:0)) {
1327 case 0:
1328 // 1 -> 2 -> 3 -> 4 -> out
1329 ch0.slot[MOD].connect = &phase_modulation;
1330 ch0.slot[CAR].connect = &phase_modulation2;
1331 ch3.slot[MOD].connect = &phase_modulation;
1332 ch3.slot[CAR].connect = &chanOut[chan_no3];
1333 break;
1334 case 1:
1335 // 1 -> 2 -\.
1336 // 3 -> 4 --+-> out
1337 ch0.slot[MOD].connect = &phase_modulation;
1338 ch0.slot[CAR].connect = &chanOut[chan_no0];
1339 ch3.slot[MOD].connect = &phase_modulation;
1340 ch3.slot[CAR].connect = &chanOut[chan_no3];
1341 break;
1342 case 2:
1343 // 1 ----------\.
1344 // 2 -> 3 -> 4 -+-> out
1345 ch0.slot[MOD].connect = &chanOut[chan_no0];
1346 ch0.slot[CAR].connect = &phase_modulation2;
1347 ch3.slot[MOD].connect = &phase_modulation;
1348 ch3.slot[CAR].connect = &chanOut[chan_no3];
1349 break;
1350 case 3:
1351 // 1 -----\.
1352 // 2 -> 3 -+-> out
1353 // 4 -----/
1354 ch0.slot[MOD].connect = &chanOut[chan_no0];
1355 ch0.slot[CAR].connect = &phase_modulation2;
1356 ch3.slot[MOD].connect = &chanOut[chan_no3];
1357 ch3.slot[CAR].connect = &chanOut[chan_no3];
1358 break;
1359 }
1360 } else {
1361 // 2 operators mode
1362 ch.slot[MOD].connect = ch.slot[MOD].CON
1363 ? &chanOut[chan_no]
1364 : &phase_modulation;
1365 ch.slot[CAR].connect = &chanOut[chan_no];
1366 }
1367 break;
1368 }
1369 case 0xE0: {
1370 // waveform select
1371 int slot = slot_array[r & 0x1f];
1372 if (slot < 0) return;
1373 slot += narrow<int>(ch_offset * 2);
1374 auto& ch = channel[slot / 2];
1375
1376 // store 3-bit value written regardless of current OPL2 or OPL3
1377 // mode... (verified on real YMF262)
1378 v &= 7;
1379 // ... but select only waveforms 0-3 in OPL2 mode
1380 if (!OPL3_mode) {
1381 v &= 3;
1382 }
1383 ch.slot[slot & 1].waveTable = sin.tab[v];
1384 break;
1385 }
1386 }
1387}
1388
1389
1390void YMF262::reset(EmuTime::param time)
1391{
1392 eg_cnt = 0;
1393
1394 noise_rng = 1; // noise shift register
1395 nts = false; // note split
1396 alreadySignaledNEW2 = false;
1397 resetStatus(0x60);
1398
1399 // reset with register write
1400 writeRegDirect(0x01, 0, time); // test register
1401 writeRegDirect(0x02, 0, time); // Timer1
1402 writeRegDirect(0x03, 0, time); // Timer2
1403 writeRegDirect(0x04, 0, time); // IRQ mask clear
1404
1405 // FIX IT registers 101, 104 and 105
1406 // FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers)
1407 for (int c = 0xFF; c >= 0x20; c--) {
1408 writeRegDirect(c, 0, time);
1409 }
1410 // FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers)
1411 for (int c = 0x1FF; c >= 0x120; c--) {
1412 writeRegDirect(c, 0, time);
1413 }
1414
1415 // reset operator parameters
1416 for (auto& ch : channel) {
1417 for (auto& sl : ch.slot) {
1418 sl.state = EG_OFF;
1419 sl.volume = MAX_ATT_INDEX;
1420 }
1421 }
1422
1423 setMixLevel(0x1b, time); // -9dB left and right
1424}
1425
1426static unsigned calcInputRate(bool isYMF278)
1427{
1428 return unsigned(lrintf(isYMF278 ? 33868800.0f / (19 * 36)
1429 : 4 * 3579545.0f / ( 8 * 36)));
1430}
1431YMF262::YMF262(const std::string& name_,
1432 const DeviceConfig& config, bool isYMF278_)
1433 : ResampledSoundDevice(config.getMotherBoard(), name_, "MoonSound FM-part",
1434 18, calcInputRate(isYMF278_), true)
1435 , debuggable(config.getMotherBoard(), getName())
1436 , timer1(isYMF278_
1437 ? EmuTimer::createOPL4_1(config.getScheduler(), *this)
1438 : EmuTimer::createOPL3_1(config.getScheduler(), *this))
1439 , timer2(isYMF278_
1440 ? EmuTimer::createOPL4_2(config.getScheduler(), *this)
1441 : EmuTimer::createOPL3_2(config.getScheduler(), *this))
1442 , irq(config.getMotherBoard(), getName() + ".IRQ")
1443 , isYMF278(isYMF278_)
1444{
1445 // For debugging: print out tables to be able to compare before/after
1446 // when the calculation changes.
1447 if (false) {
1448 for (const auto& e : tlTab) std::cout << e << '\n';
1449 std::cout << '\n';
1450 for (const auto& t : sin.tab) {
1451 for (const auto& e : t) {
1452 std::cout << e << '\n';
1453 }
1454 }
1455 }
1456
1457 registerSound(config);
1458 reset(config.getMotherBoard().getCurrentTime()); // must come after registerSound() because of call to setSoftwareVolume() via setMixLevel()
1459}
1460
1462{
1464}
1465
1467{
1468 // no need to call updateStream(time)
1469 uint8_t result = status | status2;
1470 status2 = 0;
1471 return result;
1472}
1473
1474uint8_t YMF262::peekStatus() const
1475{
1476 return status | status2;
1477}
1478
1479bool YMF262::checkMuteHelper()
1480{
1481 // TODO this doesn't always mute when possible
1482 for (auto& ch : channel) {
1483 for (auto& sl : ch.slot) {
1484 if (!((sl.state == EG_OFF) ||
1485 ((sl.state == EG_RELEASE) &&
1486 ((narrow<int>(sl.TLL) + sl.volume) >= ENV_QUIET)))) {
1487 return false;
1488 }
1489 }
1490 }
1491 return true;
1492}
1493
1494void YMF262::setMixLevel(uint8_t x, EmuTime::param time)
1495{
1496 // Only present on YMF278
1497 // see mix_level[] and vol_factor() in YMF278.cc
1498 static constexpr std::array<float, 8> level = {
1499 (1.00f / 1), // 0dB
1500 (0.75f / 1), // -3dB (approx)
1501 (1.00f / 2), // -6dB
1502 (0.75f / 2), // -9dB (approx)
1503 (1.00f / 4), // -12dB
1504 (0.75f / 4), // -15dB (approx)
1505 (1.00f / 8), // -18dB
1506 (0.00f ), // -inf dB
1507 };
1508 setSoftwareVolume(level[x & 7], level[(x >> 3) & 7], time);
1509}
1510
1511float YMF262::getAmplificationFactorImpl() const
1512{
1513 return 1.0f / 4096.0f;
1514}
1515
1516void YMF262::generateChannels(std::span<float*> bufs, unsigned num)
1517{
1518 // TODO implement per-channel mute (instead of all-or-nothing)
1519 // TODO output rhythm on separate channels?
1520 if (checkMuteHelper()) {
1521 // TODO update internal state, even if muted
1522 ranges::fill(bufs, nullptr);
1523 return;
1524 }
1525
1526 bool rhythmEnabled = (rhythm & 0x20) != 0;
1527
1528 for (auto j : xrange(num)) {
1529 // Amplitude modulation: 27 output levels (triangle waveform);
1530 // 1 level takes one of: 192, 256 or 448 samples
1531 // One entry from LFO_AM_TABLE lasts for 64 samples
1532 lfo_am_cnt.addQuantum();
1533 if (lfo_am_cnt == LFOAMIndex(LFO_AM_TAB_ELEMENTS)) {
1534 // lfo_am_table is 210 elements long
1535 lfo_am_cnt = LFOAMIndex(0);
1536 }
1537 unsigned tmp = lfo_am_table[lfo_am_cnt.toInt()];
1538 unsigned lfo_am = lfo_am_depth ? tmp : tmp / 4;
1539
1540 // clear channel outputs
1541 ranges::fill(chanOut, 0);
1542
1543 // channels 0,3 1,4 2,5 9,12 10,13 11,14
1544 // in either 2op or 4op mode
1545 for (int k = 0; k <= 9; k += 9) {
1546 for (auto i : xrange(3)) {
1547 auto& ch0 = channel[k + i + 0];
1548 auto& ch3 = channel[k + i + 3];
1549 // extended 4op ch#0 part 1 or 2op ch#0
1550 ch0.chan_calc(lfo_am);
1551 if (ch0.extended) {
1552 // extended 4op ch#0 part 2
1553 ch3.chan_calc_ext(lfo_am);
1554 } else {
1555 // standard 2op ch#3
1556 ch3.chan_calc(lfo_am);
1557 }
1558 }
1559 }
1560
1561 // channels 6,7,8 rhythm or 2op mode
1562 if (!rhythmEnabled) {
1563 channel[6].chan_calc(lfo_am);
1564 channel[7].chan_calc(lfo_am);
1565 channel[8].chan_calc(lfo_am);
1566 } else {
1567 // Rhythm part
1568 chan_calc_rhythm(lfo_am);
1569 }
1570
1571 // channels 15,16,17 are fixed 2-operator channels only
1572 channel[15].chan_calc(lfo_am);
1573 channel[16].chan_calc(lfo_am);
1574 channel[17].chan_calc(lfo_am);
1575
1576 for (auto i : xrange(18)) {
1577 bufs[i][2 * j + 0] += narrow_cast<float>(chanOut[i] & pan[4 * i + 0]);
1578 bufs[i][2 * j + 1] += narrow_cast<float>(chanOut[i] & pan[4 * i + 1]);
1579 // unused c += narrow_cast<float>(chanOut[i] & pan[4 * i + 2]);
1580 // unused d += narrow_cast<float>(chanOut[i] & pan[4 * i + 3]);
1581 }
1582
1583 advance();
1584 }
1585}
1586
1587
1588static constexpr std::initializer_list<enum_string<YMF262::EnvelopeState>> envelopeStateInfo = {
1589 { "ATTACK", YMF262::EG_ATTACK },
1590 { "DECAY", YMF262::EG_DECAY },
1591 { "SUSTAIN", YMF262::EG_SUSTAIN },
1592 { "RELEASE", YMF262::EG_RELEASE },
1593 { "OFF", YMF262::EG_OFF }
1594};
1596
1597template<typename Archive>
1598void YMF262::Slot::serialize(Archive& a, unsigned /*version*/)
1599{
1600 // waveTable
1601 auto waveform = unsigned((waveTable.data() - sin.tab[0].data()) / SIN_LEN);
1602 a.serialize("waveform", waveform);
1603 if constexpr (Archive::IS_LOADER) {
1604 waveTable = sin.tab[waveform];
1605 }
1606
1607 // done by rewriting registers:
1608 // connect, fb_shift, CON
1609 // TODO handle more state like this
1610
1611 a.serialize("Cnt", Cnt,
1612 "Incr", Incr,
1613 "op1_out", op1_out,
1614 "TL", TL,
1615 "TLL", TLL,
1616 "volume", volume,
1617 "sl", sl,
1618 "state", state,
1619 "eg_m_ar", eg_m_ar,
1620 "eg_m_dr", eg_m_dr,
1621 "eg_m_rr", eg_m_rr,
1622 "eg_sh_ar", eg_sh_ar,
1623 "eg_sel_ar", eg_sel_ar,
1624 "eg_sh_dr", eg_sh_dr,
1625 "eg_sel_dr", eg_sel_dr,
1626 "eg_sh_rr", eg_sh_rr,
1627 "eg_sel_rr", eg_sel_rr,
1628 "key", key,
1629 "eg_type", eg_type,
1630 "AMmask", AMmask,
1631 "vib", vib,
1632 "ar", ar,
1633 "dr", dr,
1634 "rr", rr,
1635 "KSR", KSR,
1636 "ksl", ksl,
1637 "ksr", ksr,
1638 "mul", mul);
1639}
1640
1641template<typename Archive>
1642void YMF262::Channel::serialize(Archive& a, unsigned /*version*/)
1643{
1644 a.serialize("slots", slot,
1645 "block_fnum", block_fnum,
1646 "fc", fc,
1647 "ksl_base", ksl_base,
1648 "kcode", kcode,
1649 "extended", extended);
1650}
1651
1652// version 1: initial version
1653// version 2: added alreadySignaledNEW2
1654template<typename Archive>
1655void YMF262::serialize(Archive& a, unsigned version)
1656{
1657 a.serialize("timer1", *timer1,
1658 "timer2", *timer2,
1659 "irq", irq,
1660 "chanout", chanOut);
1661 a.serialize_blob("registers", reg);
1662 a.serialize("channels", channel,
1663 "eg_cnt", eg_cnt,
1664 "noise_rng", noise_rng,
1665 "lfo_am_cnt", lfo_am_cnt,
1666 "lfo_pm_cnt", lfo_pm_cnt,
1667 "lfo_am_depth", lfo_am_depth,
1668 "lfo_pm_depth_range", lfo_pm_depth_range,
1669 "rhythm", rhythm,
1670 "nts", nts,
1671 "OPL3_mode", OPL3_mode,
1672 "status", status,
1673 "status2", status2,
1674 "statusMask", statusMask);
1675 if (a.versionAtLeast(version, 2)) {
1676 a.serialize("alreadySignaledNEW2", alreadySignaledNEW2);
1677 } else {
1678 assert(Archive::IS_LOADER);
1679 alreadySignaledNEW2 = true; // we can't know the actual value,
1680 // but 'true' is the safest value
1681 }
1682
1683 // TODO restore more state by rewriting register values
1684 // this handles pan
1685 EmuTime::param time = timer1->getCurrentTime();
1686 for (auto i : xrange(0xC0, 0xC9)) {
1687 writeRegDirect(i + 0x000, reg[i + 0x000], time);
1688 writeRegDirect(i + 0x100, reg[i + 0x100], time);
1689 }
1690}
1691
1693
1694
1695// YMF262::Debuggable
1696
1697YMF262::Debuggable::Debuggable(MSXMotherBoard& motherBoard_,
1698 const std::string& name_)
1699 : SimpleDebuggable(motherBoard_, name_ + " regs",
1700 "MoonSound FM-part registers", 0x200)
1701{
1702}
1703
1704uint8_t YMF262::Debuggable::read(unsigned address)
1705{
1706 auto& ymf262 = OUTER(YMF262, debuggable);
1707 return ymf262.peekReg(address);
1708}
1709
1710void YMF262::Debuggable::write(unsigned address, uint8_t value, EmuTime::param time)
1711{
1712 auto& ymf262 = OUTER(YMF262, debuggable);
1713 ymf262.writeReg512(address, value, time);
1714}
1715
1716} // namespace openmsx
TclObject t
MSXMotherBoard & getMotherBoard() const
Definition: DeviceConfig.cc:13
constexpr int toInt() const
Returns the integer part (rounded down) of this fixed point number.
Definition: FixedPoint.hh:77
constexpr void addQuantum()
Increase this value with the smallest possible amount.
Definition: FixedPoint.hh:200
void set()
Set the interrupt request on the bus.
Definition: IRQHelper.hh:74
void reset()
Reset the interrupt request on the bus.
Definition: IRQHelper.hh:83
EmuTime::param getCurrentTime()
Convenience method: This is the same as getScheduler().getCurrentTime().
void updateStream(EmuTime::param time)
Definition: SoundDevice.cc:138
void setSoftwareVolume(float volume, EmuTime::param time)
Change the 'software volume' of this sound device.
Definition: SoundDevice.cc:143
void unregisterSound()
Unregisters this sound device with the Mixer.
Definition: SoundDevice.cc:133
void registerSound(const DeviceConfig &config)
Registers this sound device with the Mixer.
Definition: SoundDevice.cc:88
static constexpr int SIN_LEN
Definition: YMF262.hh:26
void reset(EmuTime::param time)
Definition: YMF262.cc:1390
uint8_t peekStatus() const
Definition: YMF262.cc:1474
void setMixLevel(uint8_t x, EmuTime::param time)
Definition: YMF262.cc:1494
uint8_t readStatus()
Definition: YMF262.cc:1466
YMF262(const std::string &name, const DeviceConfig &config, bool isYMF278)
Definition: YMF262.cc:1431
static constexpr int SIN_BITS
Definition: YMF262.hh:25
static constexpr int SIN_MASK
Definition: YMF262.hh:27
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations
Definition: YMF262.hh:49
void serialize(Archive &ar, unsigned version)
Definition: YMF262.cc:1655
void writeReg(unsigned r, uint8_t v, EmuTime::param time)
Definition: YMF262.cc:1031
uint8_t peekReg(unsigned reg) const
Definition: YMF262.cc:1026
uint8_t readReg(unsigned reg)
Definition: YMF262.cc:1020
void writeReg512(unsigned r, uint8_t v, EmuTime::param time)
Definition: YMF262.cc:1039
constexpr double pi
Definition: Math.hh:24
constexpr double e
Definition: Math.hh:21
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:267
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations.
This file implemented 3 utility functions:
Definition: Autofire.cc:9
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
void serialize(Archive &ar, T &t, unsigned version)
constexpr void fill(ForwardRange &&range, const T &value)
Definition: ranges.hh:305
#define OUTER(type, member)
Definition: outer.hh:41
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1021
std::array< std::array< unsigned, YMF262::SIN_LEN >, 8 > tab
Definition: YMF262.cc:393
constexpr auto xrange(T e)
Definition: xrange.hh:132