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