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 case EG_ATTACK:
542 if (!(egCnt & eg_m_ar)) {
543 volume += (~volume * eg_inc[eg_sel_ar + ((egCnt >> eg_sh_ar) & 7)]) >> 3;
544 if (volume <= MIN_ATT_INDEX) {
545 volume = MIN_ATT_INDEX;
546 state = EG_DECAY;
547 }
548 }
549 break;
550
551 case EG_DECAY:
552 if (!(egCnt & eg_m_dr)) {
553 volume += eg_inc[eg_sel_dr + ((egCnt >> eg_sh_dr) & 7)];
554 if (volume >= sl) {
555 state = EG_SUSTAIN;
556 }
557 }
558 break;
559
560 case EG_SUSTAIN:
561 // this is important behaviour:
562 // one can change percussive/non-percussive
563 // modes on the fly and the chip will remain
564 // in sustain phase - verified on real YM3812
565 if (eg_type) {
566 // non-percussive mode
567 // do nothing
568 } else {
569 // percussive mode
570 // during sustain phase chip adds Release Rate (in percussive mode)
571 if (!(egCnt & eg_m_rr)) {
572 volume += eg_inc[eg_sel_rr + ((egCnt >> eg_sh_rr) & 7)];
573 if (volume >= MAX_ATT_INDEX) {
574 volume = MAX_ATT_INDEX;
575 }
576 } else {
577 // do nothing in sustain phase
578 }
579 }
580 break;
581
582 case EG_RELEASE:
583 if (!(egCnt & eg_m_rr)) {
584 volume += eg_inc[eg_sel_rr + ((egCnt >> eg_sh_rr) & 7)];
585 if (volume >= MAX_ATT_INDEX) {
586 volume = MAX_ATT_INDEX;
587 state = EG_OFF;
588 }
589 }
590 break;
591
592 default:
593 break;
594 }
595}
596
597void YMF262::Slot::advancePhaseGenerator(const Channel& ch, unsigned lfo_pm)
598{
599 if (vib) {
600 // LFO phase modulation active
601 unsigned block_fnum = ch.block_fnum;
602 unsigned fnum_lfo = (block_fnum & 0x0380) >> 7;
603 auto lfo_fn_table_index_offset = narrow_cast<int>(lfo_pm_table[lfo_pm + 16 * fnum_lfo]);
604 Cnt += fnumToIncrement(block_fnum + lfo_fn_table_index_offset) * mul;
605 } else {
606 // LFO phase modulation disabled for this operator
607 Cnt += Incr;
608 }
609}
610
611// advance to next sample
612void YMF262::advance()
613{
614 // Vibrato: 8 output levels (triangle waveform);
615 // 1 level takes 1024 samples
616 lfo_pm_cnt.addQuantum();
617 unsigned lfo_pm = (lfo_pm_cnt.toInt() & 7) | lfo_pm_depth_range;
618
619 ++eg_cnt;
620 for (auto& ch : channel) {
621 for (auto& op : ch.slot) {
622 op.advanceEnvelopeGenerator(eg_cnt);
623 op.advancePhaseGenerator(ch, lfo_pm);
624 }
625 }
626
627 // The Noise Generator of the YM3812 is 23-bit shift register.
628 // Period is equal to 2^23-2 samples.
629 // Register works at sampling frequency of the chip, so output
630 // can change on every sample.
631 //
632 // Output of the register and input to the bit 22 is:
633 // bit0 XOR bit14 XOR bit15 XOR bit22
634 //
635 // Simply use bit 22 as the noise output.
636 //
637 // unsigned j = ((noise_rng >> 0) ^ (noise_rng >> 14) ^
638 // (noise_rng >> 15) ^ (noise_rng >> 22)) & 1;
639 // noise_rng = (j << 22) | (noise_rng >> 1);
640 //
641 // Instead of doing all the logic operations above, we
642 // use a trick here (and use bit 0 as the noise output).
643 // The difference is only that the noise bit changes one
644 // step ahead. This doesn't matter since we don't know
645 // what is real state of the noise_rng after the reset.
646 if (noise_rng & 1) {
647 noise_rng ^= 0x800302;
648 }
649 noise_rng >>= 1;
650}
651
652inline int YMF262::Slot::op_calc(unsigned phase, unsigned lfo_am) const
653{
654 unsigned env = (TLL + volume + (lfo_am & AMmask)) << 4;
655 auto p = env + waveTable[phase & SIN_MASK];
656 return (p < TL_TAB_LEN) ? tlTab[p] : 0;
657}
658
659// calculate output of a standard 2 operator channel
660// (or 1st part of a 4-op channel)
661void YMF262::Channel::chan_calc(unsigned lfo_am)
662{
663 // !! something is wrong with this, it caused bug
664 // !! [2823673] MoonSound 4 operator FM fail
665 // !! optimization disabled for now
666 // !! TODO investigate
667 // !! maybe this micro optimization isn't worth the trouble/risk
668 // !!
669 // - mod.connect can point to 'phase_modulation' or 'ch0-output'
670 // - car.connect can point to 'phase_modulation2' or 'ch0-output'
671 // (see register #C0-#C8 writes)
672 // - phase_modulation2 is only used in 4op mode
673 // - mod.connect and car.connect can point to the same thing, so we need
674 // an addition for car.connect (and initialize phase_modulation2 to
675 // zero). For mod.connect we can directly assign the value.
676
677 // ?? is this paragraph correct ??
678 // phase_modulation should be initialized to zero here. But there seems
679 // to be an optimization bug in gcc-4.2: it *seems* that when we
680 // initialize phase_modulation to zero in this function, the optimizer
681 // assumes it still has value zero at the end of this function (where
682 // it's used to calculate car.connect). As a workaround we initialize
683 // phase_modulation each time before calling this function.
684 phase_modulation = 0;
685 phase_modulation2 = 0;
686
687 auto& mod = slot[MOD];
688 int out = mod.fb_shift
689 ? mod.op1_out[0] + mod.op1_out[1]
690 : 0;
691 mod.op1_out[0] = mod.op1_out[1];
692 mod.op1_out[1] = mod.op_calc(mod.Cnt.toInt() + (out >> mod.fb_shift), lfo_am);
693 *mod.connect += mod.op1_out[1];
694
695 auto& car = slot[CAR];
696 *car.connect += car.op_calc(car.Cnt.toInt() + phase_modulation, lfo_am);
697}
698
699// calculate output of a 2nd part of 4-op channel
700void YMF262::Channel::chan_calc_ext(unsigned lfo_am)
701{
702 // !! see remark in chan_cal(), something is wrong with this
703 // !! optimization disabled for now
704 // !!
705 // - mod.connect can point to 'phase_modulation' or 'ch3-output'
706 // - car.connect always points to 'ch3-output' (always 4op-mode)
707 // (see register #C0-#C8 writes)
708 // - mod.connect and car.connect can point to the same thing, so we need
709 // an addition for car.connect. For mod.connect we can directly assign
710 // the value.
711
712 phase_modulation = 0;
713
714 auto& mod = slot[MOD];
715 *mod.connect += mod.op_calc(mod.Cnt.toInt() + phase_modulation2, lfo_am);
716
717 auto& car = slot[CAR];
718 *car.connect += car.op_calc(car.Cnt.toInt() + phase_modulation, lfo_am);
719}
720
721// operators used in the rhythm sounds generation process:
722//
723// Envelope Generator:
724//
725// channel operator register number Bass High Snare Tom Top
726// / slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal
727// 6 / 0 12 50 70 90 f0 +
728// 6 / 1 15 53 73 93 f3 +
729// 7 / 0 13 51 71 91 f1 +
730// 7 / 1 16 54 74 94 f4 +
731// 8 / 0 14 52 72 92 f2 +
732// 8 / 1 17 55 75 95 f5 +
733//
734// Phase Generator:
735//
736// channel operator register number Bass High Snare Tom Top
737// / slot number MULTIPLE Drum Hat Drum Tom Cymbal
738// 6 / 0 12 30 +
739// 6 / 1 15 33 +
740// 7 / 0 13 31 + + +
741// 7 / 1 16 34 ----- n o t u s e d -----
742// 8 / 0 14 32 +
743// 8 / 1 17 35 + +
744//
745// channel operator register number Bass High Snare Tom Top
746// number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
747// 6 12,15 B6 A6 +
748//
749// 7 13,16 B7 A7 + + +
750//
751// 8 14,17 B8 A8 + + +
752
753// The following formulas can be well optimized.
754// I leave them in direct form for now (in case I've missed something).
755
756inline unsigned YMF262::genPhaseHighHat()
757{
758 // high hat phase generation (verified on real YM3812):
759 // phase = d0 or 234 (based on frequency only)
760 // phase = 34 or 2d0 (based on noise)
761
762 // base frequency derived from operator 1 in channel 7
763 int op71phase = channel[7].slot[MOD].Cnt.toInt();
764 bool bit7 = (op71phase & 0x80) != 0;
765 bool bit3 = (op71phase & 0x08) != 0;
766 bool bit2 = (op71phase & 0x04) != 0;
767 bool res1 = (bit2 ^ bit7) | bit3;
768 // when res1 = 0 phase = 0x000 | 0xd0;
769 // when res1 = 1 phase = 0x200 | (0xd0>>2);
770 unsigned phase = res1 ? (0x200 | (0xd0 >> 2)) : 0xd0;
771
772 // enable gate based on frequency of operator 2 in channel 8
773 int op82phase = channel[8].slot[CAR].Cnt.toInt();
774 bool bit5e= (op82phase & 0x20) != 0;
775 bool bit3e= (op82phase & 0x08) != 0;
776 bool res2 = (bit3e ^ bit5e);
777 // when res2 = 0 pass the phase from calculation above (res1);
778 // when res2 = 1 phase = 0x200 | (0xd0>>2);
779 if (res2) {
780 phase = (0x200 | (0xd0 >> 2));
781 }
782
783 // when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0
784 // when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change
785 if (phase & 0x200) {
786 if (noise_rng & 1) {
787 phase = 0x200 | 0xd0;
788 }
789 } else {
790 // when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2
791 // when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change
792 if (noise_rng & 1) {
793 phase = 0xd0 >> 2;
794 }
795 }
796 return phase;
797}
798
799inline unsigned YMF262::genPhaseSnare()
800{
801 // verified on real YM3812
802 // base frequency derived from operator 1 in channel 7
803 // noise bit XOR'es phase by 0x100
804 return ((channel[7].slot[MOD].Cnt.toInt() & 0x100) + 0x100)
805 ^ ((noise_rng & 1) << 8);
806}
807
808inline unsigned YMF262::genPhaseCymbal()
809{
810 // verified on real YM3812
811 // enable gate based on frequency of operator 2 in channel 8
812 // NOTE: YM2413_2 uses bit5 | bit3, this core uses bit5 ^ bit3
813 // most likely only one of the two is correct
814 int op82phase = channel[8].slot[CAR].Cnt.toInt();
815 if ((op82phase ^ (op82phase << 2)) & 0x20) { // bit5 ^ bit3
816 return 0x300;
817 } else {
818 // base frequency derived from operator 1 in channel 7
819 int op71phase = channel[7].slot[MOD].Cnt.toInt();
820 bool bit7 = (op71phase & 0x80) != 0;
821 bool bit3 = (op71phase & 0x08) != 0;
822 bool bit2 = (op71phase & 0x04) != 0;
823 return ((bit2 != bit7) || bit3) ? 0x300 : 0x100;
824 }
825}
826
827// calculate rhythm
828void YMF262::chan_calc_rhythm(unsigned lfo_am)
829{
830 // Bass Drum (verified on real YM3812):
831 // - depends on the channel 6 'connect' register:
832 // when connect = 0 it works the same as in normal (non-rhythm)
833 // mode (op1->op2->out)
834 // when connect = 1 _only_ operator 2 is present on output
835 // (op2->out), operator 1 is ignored
836 // - output sample always is multiplied by 2
837 auto& mod6 = channel[6].slot[MOD];
838 int out = mod6.fb_shift ? mod6.op1_out[0] + mod6.op1_out[1] : 0;
839 mod6.op1_out[0] = mod6.op1_out[1];
840 int pm = mod6.CON ? 0 : mod6.op1_out[0];
841 mod6.op1_out[1] = mod6.op_calc(mod6.Cnt.toInt() + (out >> mod6.fb_shift), lfo_am);
842 auto& car6 = channel[6].slot[CAR];
843 chanOut[6] += 2 * car6.op_calc(car6.Cnt.toInt() + pm, lfo_am);
844
845 // Phase generation is based on:
846 // HH (13) channel 7->slot 1 combined with channel 8->slot 2
847 // (same combination as TOP CYMBAL but different output phases)
848 // SD (16) channel 7->slot 1
849 // TOM (14) channel 8->slot 1
850 // TOP (17) channel 7->slot 1 combined with channel 8->slot 2
851 // (same combination as HIGH HAT but different output phases)
852 //
853 // Envelope generation based on:
854 // HH channel 7->slot1
855 // SD channel 7->slot2
856 // TOM channel 8->slot1
857 // TOP channel 8->slot2
858 auto& mod7 = channel[7].slot[MOD];
859 chanOut[7] += 2 * mod7.op_calc(genPhaseHighHat(), lfo_am);
860 auto& car7 = channel[7].slot[CAR];
861 chanOut[7] += 2 * car7.op_calc(genPhaseSnare(), lfo_am);
862 auto& mod8 = channel[8].slot[MOD];
863 chanOut[8] += 2 * mod8.op_calc(mod8.Cnt.toInt(), lfo_am);
864 auto& car8 = channel[8].slot[CAR];
865 chanOut[8] += 2 * car8.op_calc(genPhaseCymbal(), lfo_am);
866}
867
868void YMF262::Slot::FM_KEYON(uint8_t key_set)
869{
870 if (!key) {
871 // restart Phase Generator
872 Cnt = FreqIndex(0);
873 // phase -> Attack
874 state = EG_ATTACK;
875 }
876 key |= key_set;
877}
878
879void YMF262::Slot::FM_KEYOFF(uint8_t key_clr)
880{
881 if (key) {
882 key &= ~key_clr;
883 if (!key) {
884 // phase -> Release
885 if (state != EG_OFF) {
886 state = EG_RELEASE;
887 }
888 }
889 }
890}
891
892void YMF262::Slot::update_ar_dr()
893{
894 if ((ar + ksr) < 16 + 60) {
895 // verified on real YMF262 - all 15 x rates take "zero" time
896 eg_sh_ar = eg_rate_shift [ar + ksr];
897 eg_sel_ar = eg_rate_select[ar + ksr];
898 } else {
899 eg_sh_ar = 0;
900 eg_sel_ar = 13 * RATE_STEPS;
901 }
902 eg_m_ar = (1 << eg_sh_ar) - 1;
903 eg_sh_dr = eg_rate_shift [dr + ksr];
904 eg_sel_dr = eg_rate_select[dr + ksr];
905 eg_m_dr = (1 << eg_sh_dr) - 1;
906}
907void YMF262::Slot::update_rr()
908{
909 eg_sh_rr = eg_rate_shift [rr + ksr];
910 eg_sel_rr = eg_rate_select[rr + ksr];
911 eg_m_rr = (1 << eg_sh_rr) - 1;
912}
913
914// update phase increment counter of operator (also update the EG rates if necessary)
915void YMF262::Slot::calc_fc(const Channel& ch)
916{
917 // (frequency) phase increment counter
918 Incr = ch.fc * mul;
919
920 auto newKsr = narrow<uint8_t>(ch.kcode >> KSR);
921 if (ksr == newKsr) return;
922 ksr = newKsr;
923
924 // calculate envelope generator rates
925 update_ar_dr();
926 update_rr();
927}
928
929static constexpr std::array<unsigned, 18> channelPairTab = {
930 0, 1, 2, 0, 1, 2, unsigned(~0), unsigned(~0), unsigned(~0),
931 9, 10, 11, 9, 10, 11, unsigned(~0), unsigned(~0), unsigned(~0),
932};
933inline bool YMF262::isExtended(unsigned ch) const
934{
935 assert(ch < 18);
936 if (!OPL3_mode) return false;
937 if (channelPairTab[ch] == unsigned(~0)) return false;
938 return channel[channelPairTab[ch]].extended;
939}
940static constexpr unsigned getFirstOfPairNum(unsigned ch)
941{
942 assert((ch < 18) && (channelPairTab[ch] != unsigned(~0)));
943 return channelPairTab[ch];
944}
945inline YMF262::Channel& YMF262::getFirstOfPair(unsigned ch)
946{
947 return channel[getFirstOfPairNum(ch) + 0];
948}
949inline YMF262::Channel& YMF262::getSecondOfPair(unsigned ch)
950{
951 return channel[getFirstOfPairNum(ch) + 3];
952}
953
954// set multi,am,vib,EG-TYP,KSR,mul
955void YMF262::set_mul(unsigned sl, uint8_t v)
956{
957 unsigned chan_no = sl / 2;
958 auto& ch = channel[chan_no];
959 auto& slot = ch.slot[sl & 1];
960
961 slot.mul = mul_tab[v & 0x0f];
962 slot.KSR = (v & 0x10) ? 0 : 2;
963 slot.eg_type = (v & 0x20) != 0;
964 slot.vib = (v & 0x40) != 0;
965 slot.AMmask = (v & 0x80) ? ~0 : 0;
966
967 if (isExtended(chan_no)) {
968 // 4op mode
969 // update this slot using frequency data for 1st channel of a pair
970 slot.calc_fc(getFirstOfPair(chan_no));
971 } else {
972 // normal (OPL2 mode or 2op mode)
973 slot.calc_fc(ch);
974 }
975}
976
977// set ksl & tl
978void YMF262::set_ksl_tl(unsigned sl, uint8_t v)
979{
980 unsigned chan_no = sl / 2;
981 auto& ch = channel[chan_no];
982 auto& slot = ch.slot[sl & 1];
983
984 // This is indeed {0.0, 3.0, 1.5, 6.0} dB/oct, verified on real YMF262.
985 // Note the illogical order of 2nd and 3rd element.
986 static constexpr std::array<uint8_t, 4> ksl_shift = {31, 1, 2, 0};
987 slot.ksl = ksl_shift[v >> 6];
988
989 slot.TL = (v & 0x3F) << (ENV_BITS - 1 - 7); // 7 bits TL (bit 6 = always 0)
990
991 if (isExtended(chan_no)) {
992 // update this slot using frequency data for 1st channel of a pair
993 auto& ch0 = getFirstOfPair(chan_no);
994 slot.TLL = slot.TL + (ch0.ksl_base >> slot.ksl);
995 } else {
996 // normal
997 slot.TLL = slot.TL + (ch.ksl_base >> slot.ksl);
998 }
999}
1000
1001// set attack rate & decay rate
1002void YMF262::set_ar_dr(unsigned sl, uint8_t v)
1003{
1004 auto& ch = channel[sl / 2];
1005 auto& slot = ch.slot[sl & 1];
1006
1007 slot.ar = (v >> 4) ? narrow<uint8_t>(16 + ((v >> 4) << 2)) : 0;
1008 slot.dr = (v & 0x0F) ? narrow<uint8_t>(16 + ((v & 0x0F) << 2)) : 0;
1009 slot.update_ar_dr();
1010}
1011
1012// set sustain level & release rate
1013void YMF262::set_sl_rr(unsigned sl, uint8_t v)
1014{
1015 auto& ch = channel[sl / 2];
1016 auto& slot = ch.slot[sl & 1];
1017
1018 slot.sl = sl_tab[v >> 4];
1019 slot.rr = (v & 0x0F) ? uint8_t(16 + ((v & 0x0F) << 2)) : 0;
1020 slot.update_rr();
1021}
1022
1023uint8_t YMF262::readReg(unsigned r) const
1024{
1025 // no need to call updateStream(time)
1026 return peekReg(r);
1027}
1028
1029uint8_t YMF262::peekReg(unsigned r) const
1030{
1031 return reg[r];
1032}
1033
1034void YMF262::writeReg(unsigned r, uint8_t v, EmuTime::param time)
1035{
1036 if (!OPL3_mode && (r != 0x105)) {
1037 // in OPL2 mode the only accessible in set #2 is register 0x05
1038 r &= ~0x100;
1039 }
1040 writeReg512(r, v, time);
1041}
1042void YMF262::writeReg512(unsigned r, uint8_t v, EmuTime::param time)
1043{
1044 updateStream(time); // TODO optimize only for regs that directly influence sound
1045 writeRegDirect(r, v, time);
1046}
1047void YMF262::writeRegDirect(unsigned r, uint8_t v, EmuTime::param time)
1048{
1049 reg[r] = v;
1050
1051 unsigned ch_offset = (r & 0x100) ? 9 : 0;
1052 switch (r & 0xE0) {
1053 case 0x00: // 000-01F,100-11F: control
1054 switch (r) {
1055 case 0x000: // test register
1056 case 0x001: // test register
1057 break;
1058
1059 case 0x002: // Timer 1
1060 timer1->setValue(v);
1061 break;
1062
1063 case 0x003: // Timer 2
1064 timer2->setValue(v);
1065 break;
1066
1067 case 0x004: // IRQ clear / mask and Timer enable
1068 if (v & 0x80) {
1069 // IRQ flags clear
1070 resetStatus(0x60);
1071 } else {
1072 changeStatusMask((~v) & 0x60);
1073 timer1->setStart((v & R04_ST1) != 0, time);
1074 timer2->setStart((v & R04_ST2) != 0, time);
1075 }
1076 break;
1077
1078 case 0x008: // x,NTS,x,x, x,x,x,x
1079 nts = (v & 0x40) != 0;
1080 break;
1081
1082 case 0x100: // test register
1083 case 0x101: // test register
1084 break;
1085
1086 case 0x104:
1087 // 6 channels enable
1088 channel[ 0].extended = (v & 0x01) != 0;
1089 channel[ 1].extended = (v & 0x02) != 0;
1090 channel[ 2].extended = (v & 0x04) != 0;
1091 channel[ 9].extended = (v & 0x08) != 0;
1092 channel[10].extended = (v & 0x10) != 0;
1093 channel[11].extended = (v & 0x20) != 0;
1094 return;
1095
1096 case 0x105:
1097 // OPL3 mode when bit0=1 otherwise it is OPL2 mode
1098 OPL3_mode = v & 0x01;
1099
1100 // Verified on real YMF278: When NEW2 bit is first set, a read
1101 // from the status register (once) returns bit 1 set (0x02).
1102 // This only happens once after reset, so clearing NEW2 and
1103 // setting it again doesn't cause another change in the status
1104 // register. Also, only bit 1 changes.
1105 if ((v & 0x02) && !alreadySignaledNEW2 && isYMF278) {
1106 status2 = 0x02;
1107 alreadySignaledNEW2 = true;
1108 }
1109
1110 // following behaviour was tested on real YMF262,
1111 // switching OPL3/OPL2 modes on the fly:
1112 // - does not change the waveform previously selected
1113 // (unless when ....)
1114 // - does not update CH.A, CH.B, CH.C and CH.D output
1115 // selectors (registers c0-c8) (unless when ....)
1116 // - does not disable channels 9-17 on OPL3->OPL2 switch
1117 // - does not switch 4 operator channels back to 2
1118 // operator channels
1119 return;
1120
1121 default:
1122 break;
1123 }
1124 break;
1125
1126 case 0x20: { // am ON, vib ON, ksr, eg_type, mul
1127 int slot = slot_array[r & 0x1F];
1128 if (slot < 0) return;
1129 set_mul(slot + ch_offset * 2, v);
1130 break;
1131 }
1132 case 0x40: {
1133 int slot = slot_array[r & 0x1F];
1134 if (slot < 0) return;
1135 set_ksl_tl(slot + ch_offset * 2, v);
1136 break;
1137 }
1138 case 0x60: {
1139 int slot = slot_array[r & 0x1F];
1140 if (slot < 0) return;
1141 set_ar_dr(slot + ch_offset * 2, v);
1142 break;
1143 }
1144 case 0x80: {
1145 int slot = slot_array[r & 0x1F];
1146 if (slot < 0) return;
1147 set_sl_rr(slot + ch_offset * 2, v);
1148 break;
1149 }
1150 case 0xA0: {
1151 // note: not r != 0x1BD, only first register block
1152 if (r == 0xBD) {
1153 // am depth, vibrato depth, r,bd,sd,tom,tc,hh
1154 lfo_am_depth = (v & 0x80) != 0;
1155 lfo_pm_depth_range = (v & 0x40) ? 8 : 0;
1156 rhythm = v & 0x3F;
1157
1158 if (rhythm & 0x20) {
1159 // BD key on/off
1160 if (v & 0x10) {
1161 channel[6].slot[MOD].FM_KEYON (2);
1162 channel[6].slot[CAR].FM_KEYON (2);
1163 } else {
1164 channel[6].slot[MOD].FM_KEYOFF(2);
1165 channel[6].slot[CAR].FM_KEYOFF(2);
1166 }
1167 // HH key on/off
1168 if (v & 0x01) {
1169 channel[7].slot[MOD].FM_KEYON (2);
1170 } else {
1171 channel[7].slot[MOD].FM_KEYOFF(2);
1172 }
1173 // SD key on/off
1174 if (v & 0x08) {
1175 channel[7].slot[CAR].FM_KEYON (2);
1176 } else {
1177 channel[7].slot[CAR].FM_KEYOFF(2);
1178 }
1179 // TOM key on/off
1180 if (v & 0x04) {
1181 channel[8].slot[MOD].FM_KEYON (2);
1182 } else {
1183 channel[8].slot[MOD].FM_KEYOFF(2);
1184 }
1185 // TOP-CY key on/off
1186 if (v & 0x02) {
1187 channel[8].slot[CAR].FM_KEYON (2);
1188 } else {
1189 channel[8].slot[CAR].FM_KEYOFF(2);
1190 }
1191 } else {
1192 // BD key off
1193 channel[6].slot[MOD].FM_KEYOFF(2);
1194 channel[6].slot[CAR].FM_KEYOFF(2);
1195 // HH key off
1196 channel[7].slot[MOD].FM_KEYOFF(2);
1197 // SD key off
1198 channel[7].slot[CAR].FM_KEYOFF(2);
1199 // TOM key off
1200 channel[8].slot[MOD].FM_KEYOFF(2);
1201 // TOP-CY off
1202 channel[8].slot[CAR].FM_KEYOFF(2);
1203 }
1204 return;
1205 }
1206
1207 // keyon,block,fnum
1208 if ((r & 0x0F) > 8) {
1209 return;
1210 }
1211 unsigned chan_no = (r & 0x0F) + ch_offset;
1212 auto& ch = channel[chan_no];
1213 int block_fnum;
1214 if (!(r & 0x10)) {
1215 // a0-a8
1216 block_fnum = (ch.block_fnum & 0x1F00) | v;
1217 } else {
1218 // b0-b8
1219 block_fnum = ((v & 0x1F) << 8) | (ch.block_fnum & 0xFF);
1220 if (isExtended(chan_no)) {
1221 if (getFirstOfPairNum(chan_no) == chan_no) {
1222 // keyon/off slots of both channels
1223 // forming a 4-op channel
1224 auto& ch0 = getFirstOfPair(chan_no);
1225 auto& ch3 = getSecondOfPair(chan_no);
1226 if (v & 0x20) {
1227 ch0.slot[MOD].FM_KEYON(1);
1228 ch0.slot[CAR].FM_KEYON(1);
1229 ch3.slot[MOD].FM_KEYON(1);
1230 ch3.slot[CAR].FM_KEYON(1);
1231 } else {
1232 ch0.slot[MOD].FM_KEYOFF(1);
1233 ch0.slot[CAR].FM_KEYOFF(1);
1234 ch3.slot[MOD].FM_KEYOFF(1);
1235 ch3.slot[CAR].FM_KEYOFF(1);
1236 }
1237 } else {
1238 // do nothing
1239 }
1240 } else {
1241 // 2 operator function keyon/off
1242 if (v & 0x20) {
1243 ch.slot[MOD].FM_KEYON (1);
1244 ch.slot[CAR].FM_KEYON (1);
1245 } else {
1246 ch.slot[MOD].FM_KEYOFF(1);
1247 ch.slot[CAR].FM_KEYOFF(1);
1248 }
1249 }
1250 }
1251 // update
1252 if (ch.block_fnum != block_fnum) {
1253 ch.block_fnum = block_fnum;
1254 ch.ksl_base = ksl_tab[block_fnum >> 6];
1255 ch.fc = fnumToIncrement(block_fnum);
1256
1257 // BLK 2,1,0 bits -> bits 3,2,1 of kcode
1258 ch.kcode = (ch.block_fnum & 0x1C00) >> 9;
1259
1260 // the info below is actually opposite to what is stated
1261 // in the Manuals (verified on real YMF262)
1262 // if noteSel == 0 -> lsb of kcode is bit 10 (MSB) of fnum
1263 // if noteSel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum
1264 if (nts) {
1265 ch.kcode |= (ch.block_fnum & 0x100) >> 8; // noteSel == 1
1266 } else {
1267 ch.kcode |= (ch.block_fnum & 0x200) >> 9; // noteSel == 0
1268 }
1269 if (isExtended(chan_no)) {
1270 if (getFirstOfPairNum(chan_no) == chan_no) {
1271 // update slots of both channels
1272 // forming up 4-op channel
1273 // refresh Total Level
1274 auto& ch0 = getFirstOfPair(chan_no);
1275 auto& ch3 = getSecondOfPair(chan_no);
1276 ch0.slot[MOD].TLL = ch0.slot[MOD].TL + (ch.ksl_base >> ch0.slot[MOD].ksl);
1277 ch0.slot[CAR].TLL = ch0.slot[CAR].TL + (ch.ksl_base >> ch0.slot[CAR].ksl);
1278 ch3.slot[MOD].TLL = ch3.slot[MOD].TL + (ch.ksl_base >> ch3.slot[MOD].ksl);
1279 ch3.slot[CAR].TLL = ch3.slot[CAR].TL + (ch.ksl_base >> ch3.slot[CAR].ksl);
1280
1281 // refresh frequency counter
1282 ch0.slot[MOD].calc_fc(ch);
1283 ch0.slot[CAR].calc_fc(ch);
1284 ch3.slot[MOD].calc_fc(ch);
1285 ch3.slot[CAR].calc_fc(ch);
1286 } else {
1287 // nothing
1288 }
1289 } else {
1290 // refresh Total Level in both SLOTs of this channel
1291 ch.slot[MOD].TLL = ch.slot[MOD].TL + (ch.ksl_base >> ch.slot[MOD].ksl);
1292 ch.slot[CAR].TLL = ch.slot[CAR].TL + (ch.ksl_base >> ch.slot[CAR].ksl);
1293
1294 // refresh frequency counter in both SLOTs of this channel
1295 ch.slot[MOD].calc_fc(ch);
1296 ch.slot[CAR].calc_fc(ch);
1297 }
1298 }
1299 break;
1300 }
1301 case 0xC0: {
1302 // CH.D, CH.C, CH.B, CH.A, FB(3bits), C
1303 if ((r & 0xF) > 8) {
1304 return;
1305 }
1306 unsigned chan_no = (r & 0x0F) + ch_offset;
1307 auto& ch = channel[chan_no];
1308
1309 unsigned base = chan_no * 4;
1310 if (OPL3_mode) {
1311 // OPL3 mode
1312 pan[base + 0] = (v & 0x10) ? ~0 : 0; // ch.A
1313 pan[base + 1] = (v & 0x20) ? ~0 : 0; // ch.B
1314 pan[base + 2] = (v & 0x40) ? ~0 : 0; // ch.C
1315 pan[base + 3] = (v & 0x80) ? ~0 : 0; // ch.D
1316 } else {
1317 // OPL2 mode - always enabled
1318 pan[base + 0] = ~0; // ch.A
1319 pan[base + 1] = ~0; // ch.B
1320 pan[base + 2] = ~0; // ch.C
1321 pan[base + 3] = ~0; // ch.D
1322 }
1323
1324 ch.slot[MOD].setFeedbackShift((v >> 1) & 7);
1325 ch.slot[MOD].CON = v & 1;
1326
1327 if (isExtended(chan_no)) {
1328 unsigned chan_no0 = getFirstOfPairNum(chan_no);
1329 unsigned chan_no3 = chan_no0 + 3;
1330 auto& ch0 = getFirstOfPair(chan_no);
1331 auto& ch3 = getSecondOfPair(chan_no);
1332 switch ((ch0.slot[MOD].CON ? 2:0) | (ch3.slot[MOD].CON ? 1:0)) {
1333 case 0:
1334 // 1 -> 2 -> 3 -> 4 -> out
1335 ch0.slot[MOD].connect = &phase_modulation;
1336 ch0.slot[CAR].connect = &phase_modulation2;
1337 ch3.slot[MOD].connect = &phase_modulation;
1338 ch3.slot[CAR].connect = &chanOut[chan_no3];
1339 break;
1340 case 1:
1341 // 1 -> 2 -\.
1342 // 3 -> 4 --+-> out
1343 ch0.slot[MOD].connect = &phase_modulation;
1344 ch0.slot[CAR].connect = &chanOut[chan_no0];
1345 ch3.slot[MOD].connect = &phase_modulation;
1346 ch3.slot[CAR].connect = &chanOut[chan_no3];
1347 break;
1348 case 2:
1349 // 1 ----------\.
1350 // 2 -> 3 -> 4 -+-> out
1351 ch0.slot[MOD].connect = &chanOut[chan_no0];
1352 ch0.slot[CAR].connect = &phase_modulation2;
1353 ch3.slot[MOD].connect = &phase_modulation;
1354 ch3.slot[CAR].connect = &chanOut[chan_no3];
1355 break;
1356 case 3:
1357 // 1 -----\.
1358 // 2 -> 3 -+-> out
1359 // 4 -----/
1360 ch0.slot[MOD].connect = &chanOut[chan_no0];
1361 ch0.slot[CAR].connect = &phase_modulation2;
1362 ch3.slot[MOD].connect = &chanOut[chan_no3];
1363 ch3.slot[CAR].connect = &chanOut[chan_no3];
1364 break;
1365 }
1366 } else {
1367 // 2 operators mode
1368 ch.slot[MOD].connect = ch.slot[MOD].CON
1369 ? &chanOut[chan_no]
1370 : &phase_modulation;
1371 ch.slot[CAR].connect = &chanOut[chan_no];
1372 }
1373 break;
1374 }
1375 case 0xE0: {
1376 // waveform select
1377 int slot = slot_array[r & 0x1f];
1378 if (slot < 0) return;
1379 slot += narrow<int>(ch_offset * 2);
1380 auto& ch = channel[slot / 2];
1381
1382 // store 3-bit value written regardless of current OPL2 or OPL3
1383 // mode... (verified on real YMF262)
1384 v &= 7;
1385 // ... but select only waveforms 0-3 in OPL2 mode
1386 if (!OPL3_mode) {
1387 v &= 3;
1388 }
1389 ch.slot[slot & 1].waveTable = sin.tab[v];
1390 break;
1391 }
1392 }
1393}
1394
1395
1396void YMF262::reset(EmuTime::param time)
1397{
1398 eg_cnt = 0;
1399
1400 noise_rng = 1; // noise shift register
1401 nts = false; // note split
1402 alreadySignaledNEW2 = false;
1403 resetStatus(0x60);
1404
1405 // reset with register write
1406 writeRegDirect(0x01, 0, time); // test register
1407 writeRegDirect(0x02, 0, time); // Timer1
1408 writeRegDirect(0x03, 0, time); // Timer2
1409 writeRegDirect(0x04, 0, time); // IRQ mask clear
1410
1411 // FIX IT registers 101, 104 and 105
1412 // FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers)
1413 for (int c = 0xFF; c >= 0x20; c--) {
1414 writeRegDirect(c, 0, time);
1415 }
1416 // FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers)
1417 for (int c = 0x1FF; c >= 0x120; c--) {
1418 writeRegDirect(c, 0, time);
1419 }
1420
1421 // reset operator parameters
1422 for (auto& ch : channel) {
1423 for (auto& sl : ch.slot) {
1424 sl.state = EG_OFF;
1425 sl.volume = MAX_ATT_INDEX;
1426 }
1427 }
1428
1429 setMixLevel(0x1b, time); // -9dB left and right
1430}
1431
1432static unsigned calcInputRate(bool isYMF278)
1433{
1434 return unsigned(lrintf(isYMF278 ? 33868800.0f / (19 * 36)
1435 : 4 * 3579545.0f / ( 8 * 36)));
1436}
1437YMF262::YMF262(const std::string& name_,
1438 const DeviceConfig& config, bool isYMF278_)
1439 : ResampledSoundDevice(config.getMotherBoard(), name_, "MoonSound FM-part",
1440 18, calcInputRate(isYMF278_), true)
1441 , debuggable(config.getMotherBoard(), getName())
1442 , timer1(isYMF278_
1443 ? EmuTimer::createOPL4_1(config.getScheduler(), *this)
1444 : EmuTimer::createOPL3_1(config.getScheduler(), *this))
1445 , timer2(isYMF278_
1446 ? EmuTimer::createOPL4_2(config.getScheduler(), *this)
1447 : EmuTimer::createOPL3_2(config.getScheduler(), *this))
1448 , irq(config.getMotherBoard(), getName() + ".IRQ")
1449 , isYMF278(isYMF278_)
1450{
1451 // For debugging: print out tables to be able to compare before/after
1452 // when the calculation changes.
1453 if (false) {
1454 for (const auto& e : tlTab) std::cout << e << '\n';
1455 std::cout << '\n';
1456 for (const auto& t : sin.tab) {
1457 for (const auto& e : t) {
1458 std::cout << e << '\n';
1459 }
1460 }
1461 }
1462
1463 registerSound(config);
1464 reset(config.getMotherBoard().getCurrentTime()); // must come after registerSound() because of call to setSoftwareVolume() via setMixLevel()
1465}
1466
1468{
1470}
1471
1473{
1474 // no need to call updateStream(time)
1475 uint8_t result = status | status2;
1476 status2 = 0;
1477 return result;
1478}
1479
1480uint8_t YMF262::peekStatus() const
1481{
1482 return status | status2;
1483}
1484
1485bool YMF262::checkMuteHelper() const
1486{
1487 // TODO this doesn't always mute when possible
1488 for (auto& ch : channel) {
1489 for (auto& sl : ch.slot) {
1490 if (!((sl.state == EG_OFF) ||
1491 ((sl.state == EG_RELEASE) &&
1492 ((narrow<int>(sl.TLL) + sl.volume) >= ENV_QUIET)))) {
1493 return false;
1494 }
1495 }
1496 }
1497 return true;
1498}
1499
1500void YMF262::setMixLevel(uint8_t x, EmuTime::param time)
1501{
1502 // Only present on YMF278
1503 // see mix_level[] and vol_factor() in YMF278.cc
1504 static constexpr std::array<float, 8> level = {
1505 (1.00f / 1), // 0dB
1506 (0.75f / 1), // -3dB (approx)
1507 (1.00f / 2), // -6dB
1508 (0.75f / 2), // -9dB (approx)
1509 (1.00f / 4), // -12dB
1510 (0.75f / 4), // -15dB (approx)
1511 (1.00f / 8), // -18dB
1512 0.00f // -inf dB
1513 };
1514 setSoftwareVolume(level[x & 7], level[(x >> 3) & 7], time);
1515}
1516
1517float YMF262::getAmplificationFactorImpl() const
1518{
1519 return 1.0f / 4096.0f;
1520}
1521
1522void YMF262::generateChannels(std::span<float*> bufs, unsigned num)
1523{
1524 // TODO implement per-channel mute (instead of all-or-nothing)
1525 // TODO output rhythm on separate channels?
1526 if (checkMuteHelper()) {
1527 // TODO update internal state, even if muted
1528 ranges::fill(bufs, nullptr);
1529 return;
1530 }
1531
1532 bool rhythmEnabled = (rhythm & 0x20) != 0;
1533
1534 for (auto j : xrange(num)) {
1535 // Amplitude modulation: 27 output levels (triangle waveform);
1536 // 1 level takes one of: 192, 256 or 448 samples
1537 // One entry from LFO_AM_TABLE lasts for 64 samples
1538 lfo_am_cnt.addQuantum();
1539 if (lfo_am_cnt == LFOAMIndex(LFO_AM_TAB_ELEMENTS)) {
1540 // lfo_am_table is 210 elements long
1541 lfo_am_cnt = LFOAMIndex(0);
1542 }
1543 unsigned tmp = lfo_am_table[lfo_am_cnt.toInt()];
1544 unsigned lfo_am = lfo_am_depth ? tmp : tmp / 4;
1545
1546 // clear channel outputs
1547 ranges::fill(chanOut, 0);
1548
1549 // channels 0,3 1,4 2,5 9,12 10,13 11,14
1550 // in either 2op or 4op mode
1551 for (int k = 0; k <= 9; k += 9) {
1552 for (auto i : xrange(3)) {
1553 auto& ch0 = channel[k + i + 0];
1554 auto& ch3 = channel[k + i + 3];
1555 // extended 4op ch#0 part 1 or 2op ch#0
1556 ch0.chan_calc(lfo_am);
1557 if (ch0.extended) {
1558 // extended 4op ch#0 part 2
1559 ch3.chan_calc_ext(lfo_am);
1560 } else {
1561 // standard 2op ch#3
1562 ch3.chan_calc(lfo_am);
1563 }
1564 }
1565 }
1566
1567 // channels 6,7,8 rhythm or 2op mode
1568 if (!rhythmEnabled) {
1569 channel[6].chan_calc(lfo_am);
1570 channel[7].chan_calc(lfo_am);
1571 channel[8].chan_calc(lfo_am);
1572 } else {
1573 // Rhythm part
1574 chan_calc_rhythm(lfo_am);
1575 }
1576
1577 // channels 15,16,17 are fixed 2-operator channels only
1578 channel[15].chan_calc(lfo_am);
1579 channel[16].chan_calc(lfo_am);
1580 channel[17].chan_calc(lfo_am);
1581
1582 for (auto i : xrange(18)) {
1583 bufs[i][2 * j + 0] += narrow_cast<float>(chanOut[i] & pan[4 * i + 0]);
1584 bufs[i][2 * j + 1] += narrow_cast<float>(chanOut[i] & pan[4 * i + 1]);
1585 // unused c += narrow_cast<float>(chanOut[i] & pan[4 * i + 2]);
1586 // unused d += narrow_cast<float>(chanOut[i] & pan[4 * i + 3]);
1587 }
1588
1589 advance();
1590 }
1591}
1592
1593
1594static constexpr std::initializer_list<enum_string<YMF262::EnvelopeState>> envelopeStateInfo = {
1595 { "ATTACK", YMF262::EG_ATTACK },
1596 { "DECAY", YMF262::EG_DECAY },
1597 { "SUSTAIN", YMF262::EG_SUSTAIN },
1598 { "RELEASE", YMF262::EG_RELEASE },
1599 { "OFF", YMF262::EG_OFF }
1600};
1602
1603template<typename Archive>
1604void YMF262::Slot::serialize(Archive& a, unsigned /*version*/)
1605{
1606 // waveTable
1607 auto waveform = unsigned((waveTable.data() - sin.tab[0].data()) / SIN_LEN);
1608 a.serialize("waveform", waveform);
1609 if constexpr (Archive::IS_LOADER) {
1610 waveTable = sin.tab[waveform];
1611 }
1612
1613 // done by rewriting registers:
1614 // connect, fb_shift, CON
1615 // TODO handle more state like this
1616
1617 a.serialize("Cnt", Cnt,
1618 "Incr", Incr,
1619 "op1_out", op1_out,
1620 "TL", TL,
1621 "TLL", TLL,
1622 "volume", volume,
1623 "sl", sl,
1624 "state", state,
1625 "eg_m_ar", eg_m_ar,
1626 "eg_m_dr", eg_m_dr,
1627 "eg_m_rr", eg_m_rr,
1628 "eg_sh_ar", eg_sh_ar,
1629 "eg_sel_ar", eg_sel_ar,
1630 "eg_sh_dr", eg_sh_dr,
1631 "eg_sel_dr", eg_sel_dr,
1632 "eg_sh_rr", eg_sh_rr,
1633 "eg_sel_rr", eg_sel_rr,
1634 "key", key,
1635 "eg_type", eg_type,
1636 "AMmask", AMmask,
1637 "vib", vib,
1638 "ar", ar,
1639 "dr", dr,
1640 "rr", rr,
1641 "KSR", KSR,
1642 "ksl", ksl,
1643 "ksr", ksr,
1644 "mul", mul);
1645}
1646
1647template<typename Archive>
1648void YMF262::Channel::serialize(Archive& a, unsigned /*version*/)
1649{
1650 a.serialize("slots", slot,
1651 "block_fnum", block_fnum,
1652 "fc", fc,
1653 "ksl_base", ksl_base,
1654 "kcode", kcode,
1655 "extended", extended);
1656}
1657
1658// version 1: initial version
1659// version 2: added alreadySignaledNEW2
1660template<typename Archive>
1661void YMF262::serialize(Archive& a, unsigned version)
1662{
1663 a.serialize("timer1", *timer1,
1664 "timer2", *timer2,
1665 "irq", irq,
1666 "chanout", chanOut);
1667 a.serialize_blob("registers", reg);
1668 a.serialize("channels", channel,
1669 "eg_cnt", eg_cnt,
1670 "noise_rng", noise_rng,
1671 "lfo_am_cnt", lfo_am_cnt,
1672 "lfo_pm_cnt", lfo_pm_cnt,
1673 "lfo_am_depth", lfo_am_depth,
1674 "lfo_pm_depth_range", lfo_pm_depth_range,
1675 "rhythm", rhythm,
1676 "nts", nts,
1677 "OPL3_mode", OPL3_mode,
1678 "status", status,
1679 "status2", status2,
1680 "statusMask", statusMask);
1681 if (a.versionAtLeast(version, 2)) {
1682 a.serialize("alreadySignaledNEW2", alreadySignaledNEW2);
1683 } else {
1684 assert(Archive::IS_LOADER);
1685 alreadySignaledNEW2 = true; // we can't know the actual value,
1686 // but 'true' is the safest value
1687 }
1688
1689 // TODO restore more state by rewriting register values
1690 // this handles pan
1691 EmuTime::param time = timer1->getCurrentTime();
1692 for (auto i : xrange(0xC0, 0xC9)) {
1693 writeRegDirect(i + 0x000, reg[i + 0x000], time);
1694 writeRegDirect(i + 0x100, reg[i + 0x100], time);
1695 }
1696}
1697
1699
1700
1701// YMF262::Debuggable
1702
1704 const std::string& name_)
1705 : SimpleDebuggable(motherBoard_, name_ + " regs",
1706 "MoonSound FM-part registers", 0x200)
1707{
1708}
1709
1710uint8_t YMF262::Debuggable::read(unsigned address)
1711{
1712 auto& ymf262 = OUTER(YMF262, debuggable);
1713 return ymf262.peekReg(address);
1714}
1715
1716void YMF262::Debuggable::write(unsigned address, uint8_t value, EmuTime::param time)
1717{
1718 auto& ymf262 = OUTER(YMF262, debuggable);
1719 ymf262.writeReg512(address, value, time);
1720}
1721
1722} // 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:74
void reset()
Reset the interrupt request on the bus.
Definition IRQHelper.hh:83
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:1023
void reset(EmuTime::param time)
Definition YMF262.cc:1396
uint8_t peekStatus() const
Definition YMF262.cc:1480
void setMixLevel(uint8_t x, EmuTime::param time)
Definition YMF262.cc:1500
uint8_t readStatus()
Definition YMF262.cc:1472
YMF262(const std::string &name, const DeviceConfig &config, bool isYMF278)
Definition YMF262.cc:1437
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:1661
void writeReg(unsigned r, uint8_t v, EmuTime::param time)
Definition YMF262.cc:1034
uint8_t peekReg(unsigned reg) const
Definition YMF262.cc:1029
void writeReg512(unsigned r, uint8_t v, EmuTime::param time)
Definition YMF262.cc:1042
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:305
#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