openMSX
Y8950.cc
Go to the documentation of this file.
1 /*
2  * Based on:
3  * emu8950.c -- Y8950 emulator written by Mitsutaka Okazaki 2001
4  * heavily rewritten to fit openMSX structure
5  */
6 
7 #include "Y8950.hh"
8 #include "Y8950Periphery.hh"
9 #include "MSXAudio.hh"
10 #include "DeviceConfig.hh"
11 #include "MSXMotherBoard.hh"
12 #include "Math.hh"
13 #include "cstd.hh"
14 #include "outer.hh"
15 #include "ranges.hh"
16 #include "serialize.hh"
17 #include <algorithm>
18 #include <cmath>
19 #include <iostream>
20 
21 namespace openmsx {
22 
23 static constexpr unsigned EG_MUTE = 1 << Y8950::EG_BITS;
24 static constexpr Y8950::EnvPhaseIndex EG_DP_MAX = Y8950::EnvPhaseIndex(EG_MUTE);
25 
26 static constexpr unsigned MOD = 0;
27 static constexpr unsigned CAR = 1;
28 
29 static constexpr double EG_STEP = 0.1875; // 3/16
30 static constexpr double SL_STEP = 3.0;
31 static constexpr double TL_STEP = 0.75; // 12/16
32 static constexpr double DB_STEP = 0.1875; // 3/16
33 
34 static constexpr unsigned SL_PER_EG = 16; // SL_STEP / EG_STEP
35 static constexpr unsigned TL_PER_EG = 4; // TL_STEP / EG_STEP
36 static constexpr unsigned EG_PER_DB = 1; // EG_STEP / DB_STEP
37 
38 // PM speed(Hz) and depth(cent)
39 static constexpr double PM_SPEED = 6.4;
40 static constexpr double PM_DEPTH = 13.75 / 2;
41 static constexpr double PM_DEPTH2 = 13.75;
42 
43 // Dynamic range of sustine level
44 static constexpr int SL_BITS = 4;
45 static constexpr int SL_MUTE = 1 << SL_BITS;
46 // Size of Sintable ( 1 -- 18 can be used, but 7 -- 14 recommended.)
47 static constexpr int PG_BITS = 10;
48 static constexpr int PG_WIDTH = 1 << PG_BITS;
49 static constexpr int PG_MASK = PG_WIDTH - 1;
50 // Phase increment counter
51 static constexpr int DP_BITS = 19;
52 static constexpr int DP_BASE_BITS = DP_BITS - PG_BITS;
53 
54 // Dynamic range
55 static constexpr int DB_BITS = 9;
56 static constexpr int DB_MUTE = 1 << DB_BITS;
57 // PM table is calcurated by PM_AMP * exp2(PM_DEPTH * sin(x) / 1200)
58 static constexpr int PM_AMP_BITS = 8;
59 static constexpr int PM_AMP = 1 << PM_AMP_BITS;
60 
61 // Bits for liner value
62 static constexpr int DB2LIN_AMP_BITS = 11;
63 static constexpr int SLOT_AMP_BITS = DB2LIN_AMP_BITS;
64 
65 // Bits for Pitch and Amp modulator
66 static constexpr int PM_PG_BITS = 8;
67 static constexpr int PM_PG_WIDTH = 1 << PM_PG_BITS;
68 static constexpr int PM_DP_BITS = 16;
69 static constexpr int PM_DP_WIDTH = 1 << PM_DP_BITS;
70 static constexpr int AM_PG_BITS = 8;
71 static constexpr int AM_PG_WIDTH = 1 << AM_PG_BITS;
72 static constexpr int AM_DP_BITS = 16;
73 static constexpr int AM_DP_WIDTH = 1 << AM_DP_BITS;
74 
75 // LFO Table
76 static constexpr unsigned PM_DPHASE = unsigned(PM_SPEED * PM_DP_WIDTH / (Y8950::CLOCK_FREQ / double(Y8950::CLOCK_FREQ_DIV)));
77 
78 
79 // LFO Amplitude Modulation table (verified on real YM3812)
80 // 27 output levels (triangle waveform);
81 // 1 level takes one of: 192, 256 or 448 samples
82 //
83 // Length: 210 elements.
84 // Each of the elements has to be repeated
85 // exactly 64 times (on 64 consecutive samples).
86 // The whole table takes: 64 * 210 = 13440 samples.
87 //
88 // Verified on real YM3812 (OPL2), but I believe it's the same for Y8950
89 // because it closely matches the Y8950 AM parameters:
90 // speed = 3.7Hz
91 // depth = 4.875dB
92 // Also this approch can be easily implemented in HW, the previous one (see SVN
93 // history) could not.
94 static constexpr unsigned LFO_AM_TAB_ELEMENTS = 210;
95 static constexpr byte lfo_am_table[LFO_AM_TAB_ELEMENTS] =
96 {
97  0,0,0,0,0,0,0,
98  1,1,1,1,
99  2,2,2,2,
100  3,3,3,3,
101  4,4,4,4,
102  5,5,5,5,
103  6,6,6,6,
104  7,7,7,7,
105  8,8,8,8,
106  9,9,9,9,
107  10,10,10,10,
108  11,11,11,11,
109  12,12,12,12,
110  13,13,13,13,
111  14,14,14,14,
112  15,15,15,15,
113  16,16,16,16,
114  17,17,17,17,
115  18,18,18,18,
116  19,19,19,19,
117  20,20,20,20,
118  21,21,21,21,
119  22,22,22,22,
120  23,23,23,23,
121  24,24,24,24,
122  25,25,25,25,
123  26,26,26,
124  25,25,25,25,
125  24,24,24,24,
126  23,23,23,23,
127  22,22,22,22,
128  21,21,21,21,
129  20,20,20,20,
130  19,19,19,19,
131  18,18,18,18,
132  17,17,17,17,
133  16,16,16,16,
134  15,15,15,15,
135  14,14,14,14,
136  13,13,13,13,
137  12,12,12,12,
138  11,11,11,11,
139  10,10,10,10,
140  9,9,9,9,
141  8,8,8,8,
142  7,7,7,7,
143  6,6,6,6,
144  5,5,5,5,
145  4,4,4,4,
146  3,3,3,3,
147  2,2,2,2,
148  1,1,1,1
149 };
150 
151 //**************************************************//
152 // //
153 // Helper functions //
154 // //
155 //**************************************************//
156 
157 static inline unsigned DB_POS(int x)
158 {
159  int result = int(x / DB_STEP);
160  assert(result < DB_MUTE);
161  assert(result >= 0);
162  return result;
163 }
164 static inline unsigned DB_NEG(int x)
165 {
166  return 2 * DB_MUTE + DB_POS(x);
167 }
168 
169 //**************************************************//
170 // //
171 // Create tables //
172 // //
173 //**************************************************//
174 
175 // Linear to Log curve conversion table (for Attack rate) and vice versa.
176 // values are in the range [0 .. EG_MUTE]
177 struct AdjustTables {
178  unsigned ar[EG_MUTE];
179  unsigned ra[EG_MUTE + 1];
180 };
181 static constexpr AdjustTables makeAdjustTables()
182 {
183  AdjustTables adjust = {};
184 
185  adjust.ar[0] = EG_MUTE;
186  adjust.ra[0] = EG_MUTE;
187  auto log_eg_mute = cstd::log<6, 5>(EG_MUTE);
188  for (int i = 1; i < int(EG_MUTE); ++i) {
189  adjust.ar[i] = (EG_MUTE - 1 - EG_MUTE * cstd::log<6, 5>(i) / log_eg_mute) / 2;
190  adjust.ra[i] = cstd::pow<6, 5>(EG_MUTE, (double(EG_MUTE) - 1 - 2 * i) / EG_MUTE);
191  assert(0 <= int(adjust.ar[i]));
192  assert(0 <= int(adjust.ra[i]));
193  assert(adjust.ar[i] <= EG_MUTE);
194  assert(adjust.ra[i] <= EG_MUTE);
195  }
196  adjust.ra[EG_MUTE] = 0;
197 
198  return adjust;
199 
200  // adjust.ar[] and adjust.ra[] are each others inverse, IOW
201  // adjust.ra[adjust.ar[x]] == x
202  // (except for rounding errors).
203 }
204 static constexpr AdjustTables adjust = makeAdjustTables();
205 
206 // Table for dB(0 -- (1<<DB_BITS)) to Liner(0 -- DB2LIN_AMP_WIDTH)
207 struct Db2LinTab {
208  int tab[(2 * DB_MUTE) * 2];
209 };
210 static constexpr Db2LinTab makeDB2LinTable()
211 {
212  Db2LinTab dB2Lin = {};
213 
214  for (int i = 0; i < DB_MUTE; ++i) {
215  dB2Lin.tab[i] = int(double((1 << DB2LIN_AMP_BITS) - 1) *
216  cstd::pow<7, 3>(10, -double(i) * DB_STEP / 20.0));
217  }
218  assert(dB2Lin.tab[DB_MUTE - 1] == 0);
219  for (int i = DB_MUTE; i < 2 * DB_MUTE; ++i) {
220  dB2Lin.tab[i] = 0;
221  }
222  for (int i = 0; i < 2 * DB_MUTE; ++i) {
223  dB2Lin.tab[i + 2 * DB_MUTE] = -dB2Lin.tab[i];
224  }
225 
226  return dB2Lin;
227 }
228 static constexpr Db2LinTab dB2Lin = makeDB2LinTable();
229 
230 // Liner(+0.0 - +1.0) to dB(DB_MUTE-1 -- 0)
231 static constexpr unsigned lin2db(double d)
232 {
233  if (d < 1e-4) {
234  // (almost) zero
235  return DB_MUTE - 1;
236  }
237  int tmp = -int(20.0 * cstd::log10<6, 2>(d) / DB_STEP);
238  int result = std::min(tmp, DB_MUTE - 1);
239  assert(result >= 0);
240  assert(result <= DB_MUTE - 1);
241  return result;
242 }
243 
244 // WaveTable for each envelope amp.
245 // values are in range[ 0, DB_MUTE) (for positive values)
246 // or [2*DB_MUTE, 3*DB_MUTE) (for negative values)
247 struct SinTable {
248  unsigned table[PG_WIDTH];
249 };
250 static constexpr SinTable makeSinTable()
251 {
252  SinTable sin = {};
253  for (int i = 0; i < PG_WIDTH / 4; ++i) {
254  sin.table[i] = lin2db(cstd::sin<2>(2.0 * M_PI * i / PG_WIDTH));
255  }
256  for (int i = 0; i < PG_WIDTH / 4; i++) {
257  sin.table[PG_WIDTH / 2 - 1 - i] = sin.table[i];
258  }
259  for (int i = 0; i < PG_WIDTH / 2; i++) {
260  sin.table[PG_WIDTH / 2 + i] = 2 * DB_MUTE + sin.table[i];
261  }
262  return sin;
263 }
264 static constexpr SinTable sin = makeSinTable();
265 
266 // Table for Pitch Modulator
267 struct PmTable {
268  int table[2][PM_PG_WIDTH];
269 };
270 static constexpr PmTable makePmTable()
271 {
272  PmTable pm = {};
273  for (int i = 0; i < PM_PG_WIDTH; ++i) {
274  auto s = cstd::sin<5>(2.0 * M_PI * i / PM_PG_WIDTH) / 1200;
275  pm.table[0][i] = int(PM_AMP * cstd::exp2<2>(PM_DEPTH * s));
276  pm.table[1][i] = int(PM_AMP * cstd::exp2<2>(PM_DEPTH2 * s));
277  }
278  return pm;
279 }
280 static constexpr PmTable pm = makePmTable();
281 
282 // TL Table.
283 struct TllTable {
284  int table[16 * 8][4];
285 };
286 static constexpr TllTable makeTllTable()
287 {
288  TllTable tll = {};
289 
290  // Processed version of Table 3.5 from the Application Manual
291  constexpr unsigned kltable[16] = {
292  0, 24, 32, 37, 40, 43, 45, 47, 48, 50, 51, 52, 53, 54, 55, 56
293  };
294  // This is indeed {0.0, 3.0, 1.5, 6.0} dB/oct, verified on real Y8950.
295  // Note the illogical order of 2nd and 3rd element.
296  constexpr unsigned shift[4] = { 31, 1, 2, 0 };
297 
298  for (unsigned freq = 0; freq < 16 * 8; ++freq) {
299  unsigned fnum = freq % 16;
300  unsigned block = freq / 16;
301  int tmp = 4 * kltable[fnum] - 32 * (7 - block);
302  for (unsigned KL = 0; KL < 4; ++KL) {
303  tll.table[freq][KL] = (tmp <= 0) ? 0 : (tmp >> shift[KL]);
304  }
305  }
306 
307  return tll;
308 }
309 static constexpr TllTable tllTable = makeTllTable();
310 
311 // Phase incr table for Attack.
312 struct DPhaseTable {
313  Y8950::EnvPhaseIndex table[16][16];
314 };
315 static constexpr DPhaseTable makeDphaseARTable()
316 {
317  DPhaseTable dphaseAR = {};
318  for (unsigned Rks = 0; Rks < 16; ++Rks) {
319  dphaseAR.table[Rks][0] = Y8950::EnvPhaseIndex(0);
320  for (unsigned AR = 1; AR < 15; ++AR) {
321  unsigned RM = std::min(AR + (Rks >> 2), 15u);
322  unsigned RL = Rks & 3;
323  dphaseAR.table[Rks][AR] =
324  Y8950::EnvPhaseIndex(12 * (RL + 4)) >> (15 - RM);
325  }
326  dphaseAR.table[Rks][15] = EG_DP_MAX;
327  }
328  return dphaseAR;
329 }
330 static constexpr DPhaseTable dphaseAR = makeDphaseARTable();
331 
332 // Phase incr table for Decay and Release.
333 static constexpr DPhaseTable makeDphaseDRTable()
334 {
335  DPhaseTable dphaseDR = {};
336  for (unsigned Rks = 0; Rks < 16; ++Rks) {
337  dphaseDR.table[Rks][0] = Y8950::EnvPhaseIndex(0);
338  for (unsigned DR = 1; DR < 16; ++DR) {
339  unsigned RM = std::min(DR + (Rks >> 2), 15u);
340  unsigned RL = Rks & 3;
341  dphaseDR.table[Rks][DR] =
342  Y8950::EnvPhaseIndex(RL + 4) >> (15 - RM);
343  }
344  }
345  return dphaseDR;
346 }
347 static constexpr DPhaseTable dphaseDR = makeDphaseDRTable();
348 
349 
350 // class Y8950::Patch
351 
352 Y8950::Patch::Patch()
353 {
354  reset();
355 }
356 
357 void Y8950::Patch::reset()
358 {
359  AM = false;
360  PM = false;
361  EG = false;
362  ML = 0;
363  KL = 0;
364  TL = 0;
365  AR = 0;
366  DR = 0;
367  SL = 0;
368  RR = 0;
369  setKeyScaleRate(false);
370  setFeedbackShift(0);
371 }
372 
373 
374 // class Y8950::Slot
375 
376 void Y8950::Slot::reset()
377 {
378  phase = 0;
379  output = 0;
380  feedback = 0;
381  eg_mode = FINISH;
382  eg_phase = EG_DP_MAX;
383  key = 0;
384  patch.reset();
385 
386  // this initializes:
387  // dphase, tll, dphaseARTableRks, dphaseDRTableRks, eg_dphase
388  updateAll(0);
389 }
390 
391 void Y8950::Slot::updatePG(unsigned freq)
392 {
393  static const int mltable[16] = {
394  1, 1*2, 2*2, 3*2, 4*2, 5*2, 6*2 , 7*2,
395  8*2, 9*2, 10*2, 10*2, 12*2, 12*2, 15*2, 15*2
396  };
397 
398  unsigned fnum = freq % 1024;
399  unsigned block = freq / 1024;
400  dphase = ((fnum * mltable[patch.ML]) << block) >> (21 - DP_BITS);
401 }
402 
403 void Y8950::Slot::updateTLL(unsigned freq)
404 {
405  tll = tllTable.table[freq >> 6][patch.KL] + patch.TL * TL_PER_EG;
406 }
407 
408 void Y8950::Slot::updateRKS(unsigned freq)
409 {
410  unsigned rks = freq >> patch.KR;
411  assert(rks < 16);
412  dphaseARTableRks = dphaseAR.table[rks];
413  dphaseDRTableRks = dphaseDR.table[rks];
414 }
415 
416 void Y8950::Slot::updateEG()
417 {
418  switch (eg_mode) {
419  case ATTACK:
420  eg_dphase = dphaseARTableRks[patch.AR];
421  break;
422  case DECAY:
423  eg_dphase = dphaseDRTableRks[patch.DR];
424  break;
425  case SUSTAIN:
426  case RELEASE:
427  eg_dphase = dphaseDRTableRks[patch.RR];
428  break;
429  case FINISH:
430  eg_dphase = Y8950::EnvPhaseIndex(0);
431  break;
432  }
433 }
434 
435 void Y8950::Slot::updateAll(unsigned freq)
436 {
437  updatePG(freq);
438  updateTLL(freq);
439  updateRKS(freq);
440  updateEG(); // EG should be last
441 }
442 
443 bool Y8950::Slot::isActive() const
444 {
445  return eg_mode != FINISH;
446 }
447 
448 // Slot key on
449 void Y8950::Slot::slotOn(KeyPart part)
450 {
451  if (!key) {
452  eg_mode = ATTACK;
453  phase = 0;
454  eg_phase = Y8950::EnvPhaseIndex(adjust.ra[eg_phase.toInt()]);
455  }
456  key |= part;
457 }
458 
459 // Slot key off
460 void Y8950::Slot::slotOff(KeyPart part)
461 {
462  if (key) {
463  key &= ~part;
464  if (!key) {
465  if (eg_mode == ATTACK) {
466  eg_phase = Y8950::EnvPhaseIndex(adjust.ar[eg_phase.toInt()]);
467  }
468  eg_mode = RELEASE;
469  }
470  }
471 }
472 
473 
474 // class Y8950::Channel
475 
476 Y8950::Channel::Channel()
477 {
478  reset();
479 }
480 
481 void Y8950::Channel::reset()
482 {
483  setFreq(0);
484  slot[MOD].reset();
485  slot[CAR].reset();
486  alg = false;
487 }
488 
489 // Set frequency (combined F-Number (10bit) and Block (3bit))
490 void Y8950::Channel::setFreq(unsigned freq_)
491 {
492  freq = freq_;
493 }
494 
495 void Y8950::Channel::keyOn(KeyPart part)
496 {
497  slot[MOD].slotOn(part);
498  slot[CAR].slotOn(part);
499 }
500 
501 void Y8950::Channel::keyOff(KeyPart part)
502 {
503  slot[MOD].slotOff(part);
504  slot[CAR].slotOff(part);
505 }
506 
507 
508 Y8950::Y8950(const std::string& name_, const DeviceConfig& config,
509  unsigned sampleRam, EmuTime::param time, MSXAudio& audio)
510  : ResampledSoundDevice(config.getMotherBoard(), name_, "MSX-AUDIO", 9 + 5 + 1)
511  , motherBoard(config.getMotherBoard())
512  , periphery(audio.createPeriphery(getName()))
513  , adpcm(*this, config, name_, sampleRam)
514  , connector(motherBoard.getPluggingController())
515  , dac13(name_ + " DAC", "MSX-AUDIO 13-bit DAC", config)
516  , debuggable(motherBoard, getName())
517  , timer1(EmuTimer::createOPL3_1(motherBoard.getScheduler(), *this))
518  , timer2(EmuTimer::createOPL3_2(motherBoard.getScheduler(), *this))
519  , irq(motherBoard, getName() + ".IRQ")
520  , enabled(true)
521 {
522  // For debugging: print out tables to be able to compare before/after
523  // when the calculation changes.
524  if (false) {
525  for (int i = 0; i < PM_PG_WIDTH; ++i) {
526  std::cout << pm.table[0][i] << ' '
527  << pm.table[1][i] << '\n';
528  }
529  std::cout << '\n';
530 
531  for (unsigned i = 0; i < EG_MUTE; ++i) {
532  std::cout << adjust.ra[i] << ' '
533  << adjust.ar[i] << '\n';
534  }
535  std::cout << adjust.ra[EG_MUTE] << "\n\n";
536 
537  for (auto& e : dB2Lin.tab) std::cout << e << '\n';
538  std::cout << '\n';
539 
540  for (int i = 0; i < (16 * 8); ++i) {
541  for (int j = 0; j < 4; ++j) {
542  std::cout << tllTable.table[i][j] << ' ';
543  }
544  std::cout << '\n';
545  }
546  std::cout << '\n';
547 
548  for (auto& e : sin.table) std::cout << e << '\n';
549  std::cout << '\n';
550 
551  for (int i = 0; i < 16; ++i) {
552  for (int j = 0; j < 16; ++j) {
553  std::cout << dphaseAR.table[i][j].getRawValue() << ' ';
554  }
555  std::cout << '\n';
556  }
557  std::cout << '\n';
558 
559  for (int i = 0; i < 16; ++i) {
560  for (int j = 0; j < 16; ++j) {
561  std::cout << dphaseDR.table[i][j].getRawValue() << ' ';
562  }
563  std::cout << '\n';
564  }
565  std::cout << '\n';
566  }
567 
568  float input = Y8950::CLOCK_FREQ / float(Y8950::CLOCK_FREQ_DIV);
569  setInputRate(lrintf(input));
570 
571  reset(time);
572  registerSound(config);
573 }
574 
576 {
577  unregisterSound();
578 }
579 
581 {
582  adpcm.clearRam();
583 }
584 
585 // Reset whole of opl except patch datas.
586 void Y8950::reset(EmuTime::param time)
587 {
588  for (auto& c : ch) c.reset();
589 
590  rythm_mode = false;
591  am_mode = false;
592  pm_mode = false;
593  pm_phase = 0;
594  am_phase = 0;
595  noise_seed = 0xffff;
596  noiseA_phase = 0;
597  noiseB_phase = 0;
598  noiseA_dphase = 0;
599  noiseB_dphase = 0;
600 
601  // update the output buffer before changing the register
602  updateStream(time);
603  ranges::fill(reg, 0x00);
604 
605  reg[0x04] = 0x18;
606  reg[0x19] = 0x0F; // fixes 'Thunderbirds are Go'
607  status = 0x00;
608  statusMask = 0;
609  irq.reset();
610 
611  adpcm.reset(time);
612 }
613 
614 
615 // Drum key on
616 void Y8950::keyOn_BD() { ch[6].keyOn(KEY_RHYTHM); }
617 void Y8950::keyOn_HH() { ch[7].slot[MOD].slotOn(KEY_RHYTHM); }
618 void Y8950::keyOn_SD() { ch[7].slot[CAR].slotOn(KEY_RHYTHM); }
619 void Y8950::keyOn_TOM() { ch[8].slot[MOD].slotOn(KEY_RHYTHM); }
620 void Y8950::keyOn_CYM() { ch[8].slot[CAR].slotOn(KEY_RHYTHM); }
621 
622 // Drum key off
623 void Y8950::keyOff_BD() { ch[6].keyOff(KEY_RHYTHM); }
624 void Y8950::keyOff_HH() { ch[7].slot[MOD].slotOff(KEY_RHYTHM); }
625 void Y8950::keyOff_SD() { ch[7].slot[CAR].slotOff(KEY_RHYTHM); }
626 void Y8950::keyOff_TOM(){ ch[8].slot[MOD].slotOff(KEY_RHYTHM); }
627 void Y8950::keyOff_CYM(){ ch[8].slot[CAR].slotOff(KEY_RHYTHM); }
628 
629 // Change Rhythm Mode
630 void Y8950::setRythmMode(int data)
631 {
632  bool newMode = (data & 32) != 0;
633  if (rythm_mode != newMode) {
634  rythm_mode = newMode;
635  if (!rythm_mode) {
636  // ON->OFF
637  keyOff_BD(); // TODO keyOff() or immediately to FINISH?
638  keyOff_HH(); // other variants use keyOff(), but
639  keyOff_SD(); // verify on real HW
640  keyOff_TOM();
641  keyOff_CYM();
642  }
643  }
644 }
645 
646 // recalculate 'key' from register settings
647 void Y8950::update_key_status()
648 {
649  for (unsigned i = 0; i < 9; ++i) {
650  int main = (reg[0xb0 + i] & 0x20) ? KEY_MAIN : 0;
651  ch[i].slot[MOD].key = main;
652  ch[i].slot[CAR].key = main;
653  }
654  if (rythm_mode) {
655  ch[6].slot[MOD].key |= (reg[0xbd] & 0x10) ? KEY_RHYTHM : 0; // BD1
656  ch[6].slot[CAR].key |= (reg[0xbd] & 0x10) ? KEY_RHYTHM : 0; // BD2
657  ch[7].slot[MOD].key |= (reg[0xbd] & 0x01) ? KEY_RHYTHM : 0; // HH
658  ch[7].slot[CAR].key |= (reg[0xbd] & 0x08) ? KEY_RHYTHM : 0; // SD
659  ch[8].slot[MOD].key |= (reg[0xbd] & 0x04) ? KEY_RHYTHM : 0; // TOM
660  ch[8].slot[CAR].key |= (reg[0xbd] & 0x02) ? KEY_RHYTHM : 0; // CYM
661  }
662 }
663 
664 
665 //
666 // Generate wave data
667 //
668 
669 // Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI).
670 static inline int wave2_8pi(int e)
671 {
672  int shift = SLOT_AMP_BITS - PG_BITS - 2;
673  return (shift > 0) ? (e >> shift) : (e << -shift);
674 }
675 
676 unsigned Y8950::Slot::calc_phase(int lfo_pm)
677 {
678  if (patch.PM) {
679  phase += (dphase * lfo_pm) >> PM_AMP_BITS;
680  } else {
681  phase += dphase;
682  }
683  return phase >> DP_BASE_BITS;
684 }
685 
686 #define S2E(x) Y8950::EnvPhaseIndex(int((x) / EG_STEP))
687 static constexpr Y8950::EnvPhaseIndex SL[16] = {
688  S2E( 0), S2E( 3), S2E( 6), S2E( 9), S2E(12), S2E(15), S2E(18), S2E(21),
689  S2E(24), S2E(27), S2E(30), S2E(33), S2E(36), S2E(39), S2E(42), S2E(93)
690 };
691 unsigned Y8950::Slot::calc_envelope(int lfo_am)
692 {
693  unsigned egout = 0;
694  switch (eg_mode) {
695  case ATTACK:
696  eg_phase += eg_dphase;
697  if (eg_phase >= EG_DP_MAX) {
698  egout = 0;
699  eg_phase = Y8950::EnvPhaseIndex(0);
700  eg_mode = DECAY;
701  updateEG();
702  } else {
703  egout = adjust.ar[eg_phase.toInt()];
704  }
705  break;
706 
707  case DECAY:
708  eg_phase += eg_dphase;
709  if (eg_phase >= SL[patch.SL]) {
710  eg_phase = SL[patch.SL];
711  eg_mode = SUSTAIN;
712  updateEG();
713  }
714  egout = eg_phase.toInt();
715  break;
716 
717  case SUSTAIN:
718  if (!patch.EG) {
719  eg_phase += eg_dphase;
720  }
721  egout = eg_phase.toInt();
722  if (egout >= EG_MUTE) {
723  eg_phase = EG_DP_MAX;
724  eg_mode = FINISH;
725  egout = EG_MUTE - 1;
726  }
727  break;
728 
729  case RELEASE:
730  eg_phase += eg_dphase;
731  egout = eg_phase.toInt();
732  if (egout >= EG_MUTE) {
733  eg_phase = EG_DP_MAX;
734  eg_mode = FINISH;
735  egout = EG_MUTE - 1;
736  }
737  break;
738 
739  case FINISH:
740  egout = EG_MUTE - 1;
741  break;
742  }
743 
744  egout = ((egout + tll) * EG_PER_DB);
745  if (patch.AM) {
746  egout += lfo_am;
747  }
748  return std::min<unsigned>(egout, DB_MUTE - 1);
749 }
750 
751 int Y8950::Slot::calc_slot_car(int lfo_pm, int lfo_am, int fm)
752 {
753  unsigned egout = calc_envelope(lfo_am);
754  int pgout = calc_phase(lfo_pm) + wave2_8pi(fm);
755  return dB2Lin.tab[sin.table[pgout & PG_MASK] + egout];
756 }
757 
758 int Y8950::Slot::calc_slot_mod(int lfo_pm, int lfo_am)
759 {
760  unsigned egout = calc_envelope(lfo_am);
761  unsigned pgout = calc_phase(lfo_pm);
762 
763  if (patch.FB != 0) {
764  pgout += wave2_8pi(feedback) >> patch.FB;
765  }
766  int newOutput = dB2Lin.tab[sin.table[pgout & PG_MASK] + egout];
767  feedback = (output + newOutput) >> 1;
768  output = newOutput;
769  return feedback;
770 }
771 
772 int Y8950::Slot::calc_slot_tom(int lfo_pm, int lfo_am)
773 {
774  unsigned egout = calc_envelope(lfo_am);
775  unsigned pgout = calc_phase(lfo_pm);
776  return dB2Lin.tab[sin.table[pgout & PG_MASK] + egout];
777 }
778 
779 int Y8950::Slot::calc_slot_snare(int lfo_pm, int lfo_am, int whitenoise)
780 {
781  unsigned egout = calc_envelope(lfo_am);
782  unsigned pgout = calc_phase(lfo_pm);
783  unsigned tmp = (pgout & (1 << (PG_BITS - 1))) ? 0 : 2 * DB_MUTE;
784  return (dB2Lin.tab[tmp + egout] + dB2Lin.tab[egout + whitenoise]) >> 1;
785 }
786 
787 int Y8950::Slot::calc_slot_cym(int lfo_am, int a, int b)
788 {
789  unsigned egout = calc_envelope(lfo_am);
790  return (dB2Lin.tab[egout + a] + dB2Lin.tab[egout + b]) >> 1;
791 }
792 
793 // HI-HAT
794 int Y8950::Slot::calc_slot_hat(int lfo_am, int a, int b, int whitenoise)
795 {
796  unsigned egout = calc_envelope(lfo_am);
797  return (dB2Lin.tab[egout + whitenoise] +
798  dB2Lin.tab[egout + a] +
799  dB2Lin.tab[egout + b]) >> 2;
800 }
801 
802 int Y8950::getAmplificationFactorImpl() const
803 {
804  return 1 << (15 - DB2LIN_AMP_BITS);
805 }
806 
807 void Y8950::setEnabled(bool enabled_, EmuTime::param time)
808 {
809  updateStream(time);
810  enabled = enabled_;
811 }
812 
813 bool Y8950::checkMuteHelper()
814 {
815  if (!enabled) {
816  return true;
817  }
818  for (int i = 0; i < 6; ++i) {
819  if (ch[i].slot[CAR].isActive()) return false;
820  }
821  if (!rythm_mode) {
822  for(int i = 6; i < 9; ++i) {
823  if (ch[i].slot[CAR].isActive()) return false;
824  }
825  } else {
826  if (ch[6].slot[CAR].isActive()) return false;
827  if (ch[7].slot[MOD].isActive()) return false;
828  if (ch[7].slot[CAR].isActive()) return false;
829  if (ch[8].slot[MOD].isActive()) return false;
830  if (ch[8].slot[CAR].isActive()) return false;
831  }
832 
833  return adpcm.isMuted();
834 }
835 
836 void Y8950::generateChannels(int** bufs, unsigned num)
837 {
838  // TODO implement per-channel mute (instead of all-or-nothing)
839  if (checkMuteHelper()) {
840  // TODO update internal state even when muted
841  // during mute pm_phase, am_phase, noiseA_phase, noiseB_phase
842  // and noise_seed aren't updated, probably ok
843  for (int i = 0; i < 9 + 5 + 1; ++i) {
844  bufs[i] = nullptr;
845  }
846  return;
847  }
848 
849  for (unsigned sample = 0; sample < num; ++sample) {
850  // Amplitude modulation: 27 output levels (triangle waveform);
851  // 1 level takes one of: 192, 256 or 448 samples
852  // One entry from LFO_AM_TABLE lasts for 64 samples
853  // lfo_am_table is 210 elements long
854  ++am_phase;
855  if (am_phase == (LFO_AM_TAB_ELEMENTS * 64)) am_phase = 0;
856  unsigned tmp = lfo_am_table[am_phase / 64];
857  int lfo_am = am_mode ? tmp : tmp / 4;
858 
859  pm_phase = (pm_phase + PM_DPHASE) & (PM_DP_WIDTH - 1);
860  int lfo_pm = pm.table[pm_mode][pm_phase >> (PM_DP_BITS - PM_PG_BITS)];
861 
862  if (noise_seed & 1) {
863  noise_seed ^= 0x24000;
864  }
865  noise_seed >>= 1;
866  int whitenoise = noise_seed & 1 ? DB_POS(6) : DB_NEG(6);
867 
868  noiseA_phase += noiseA_dphase;
869  noiseA_phase &= (0x40 << 11) - 1;
870  if ((noiseA_phase >> 11) == 0x3f) {
871  noiseA_phase = 0;
872  }
873  int noiseA = noiseA_phase & (0x03 << 11) ? DB_POS(6) : DB_NEG(6);
874 
875  noiseB_phase += noiseB_dphase;
876  noiseB_phase &= (0x10 << 11) - 1;
877  int noiseB = noiseB_phase & (0x0A << 11) ? DB_POS(6) : DB_NEG(6);
878 
879  int m = rythm_mode ? 6 : 9;
880  for (int i = 0; i < m; ++i) {
881  if (ch[i].slot[CAR].isActive()) {
882  bufs[i][sample] += ch[i].alg
883  ? ch[i].slot[CAR].calc_slot_car(lfo_pm, lfo_am, 0) +
884  ch[i].slot[MOD].calc_slot_mod(lfo_pm, lfo_am)
885  : ch[i].slot[CAR].calc_slot_car(lfo_pm, lfo_am,
886  ch[i].slot[MOD].calc_slot_mod(lfo_pm, lfo_am));
887  } else {
888  //bufs[i][sample] += 0;
889  }
890  }
891  if (rythm_mode) {
892  //bufs[6][sample] += 0;
893  //bufs[7][sample] += 0;
894  //bufs[8][sample] += 0;
895 
896  // TODO wasn't in original source either
897  ch[7].slot[MOD].calc_phase(lfo_pm);
898  ch[8].slot[CAR].calc_phase(lfo_pm);
899 
900  bufs[ 9][sample] += (ch[6].slot[CAR].isActive())
901  ? 2 * ch[6].slot[CAR].calc_slot_car(lfo_pm, lfo_am,
902  ch[6].slot[MOD].calc_slot_mod(lfo_pm, lfo_am))
903  : 0;
904  bufs[10][sample] += (ch[7].slot[CAR].isActive())
905  ? 2 * ch[7].slot[CAR].calc_slot_snare(lfo_pm, lfo_am, whitenoise)
906  : 0;
907  bufs[11][sample] += (ch[8].slot[CAR].isActive())
908  ? 2 * ch[8].slot[CAR].calc_slot_cym(lfo_am, noiseA, noiseB)
909  : 0;
910  bufs[12][sample] += (ch[7].slot[MOD].isActive())
911  ? 2 * ch[7].slot[MOD].calc_slot_hat(lfo_am, noiseA, noiseB, whitenoise)
912  : 0;
913  bufs[13][sample] += (ch[8].slot[MOD].isActive())
914  ? 2 * ch[8].slot[MOD].calc_slot_tom(lfo_pm, lfo_am)
915  : 0;
916  } else {
917  //bufs[ 9] += 0;
918  //bufs[10] += 0;
919  //bufs[11] += 0;
920  //bufs[12] += 0;
921  //bufs[13] += 0;
922  }
923 
924  bufs[14][sample] += adpcm.calcSample();
925  }
926 }
927 
928 //
929 // I/O Ctrl
930 //
931 
932 void Y8950::writeReg(byte rg, byte data, EmuTime::param time)
933 {
934  int stbl[32] = {
935  0, 2, 4, 1, 3, 5, -1, -1,
936  6, 8, 10, 7, 9, 11, -1, -1,
937  12, 14, 16, 13, 15, 17, -1, -1,
938  -1, -1, -1, -1, -1, -1, -1, -1
939  };
940 
941  // TODO only for registers that influence sound
942  // TODO also ADPCM
943  //if (rg >= 0x20) {
944  // update the output buffer before changing the register
945  updateStream(time);
946  //}
947 
948  switch (rg & 0xe0) {
949  case 0x00: {
950  switch (rg) {
951  case 0x01: // TEST
952  // TODO
953  // Y8950 MSX-AUDIO Test register $01 (write only)
954  //
955  // Bit Description
956  //
957  // 7 Reset LFOs - seems to force the LFOs to their initial
958  // values (eg. maximum amplitude, zero phase deviation)
959  //
960  // 6 something to do with ADPCM - bit 0 of the status
961  // register is affected by setting this bit (PCM BSY)
962  //
963  // 5 No effect? - Waveform select enable in YM3812 OPL2 so seems
964  // reasonable that this bit wouldn't have been used in OPL
965  //
966  // 4 No effect?
967  //
968  // 3 Faster LFOs - increases the frequencies of the LFOs and
969  // (maybe) the timers (cf. YM2151 test register)
970  //
971  // 2 Reset phase generators - No phase generator output, but
972  // envelope generators still work (can hear a transient
973  // when they are gated)
974  //
975  // 1 No effect?
976  //
977  // 0 Reset envelopes - Envelope generator outputs forced
978  // to maximum, so all enabled voices sound at maximum
979  reg[rg] = data;
980  break;
981 
982  case 0x02: // TIMER1 (reso. 80us)
983  timer1->setValue(data);
984  reg[rg] = data;
985  break;
986 
987  case 0x03: // TIMER2 (reso. 320us)
988  timer2->setValue(data);
989  reg[rg] = data;
990  break;
991 
992  case 0x04: // FLAG CONTROL
993  if (data & Y8950::R04_IRQ_RESET) {
994  resetStatus(0x78); // reset all flags
995  } else {
996  changeStatusMask((~data) & 0x78);
997  timer1->setStart((data & Y8950::R04_ST1) != 0, time);
998  timer2->setStart((data & Y8950::R04_ST2) != 0, time);
999  reg[rg] = data;
1000  }
1001  adpcm.resetStatus();
1002  break;
1003 
1004  case 0x06: // (KEYBOARD OUT)
1005  connector.write(data, time);
1006  reg[rg] = data;
1007  break;
1008 
1009  case 0x07: // START/REC/MEM DATA/REPEAT/SP-OFF/-/-/RESET
1010  periphery.setSPOFF((data & 8) != 0, time); // bit 3
1011  // fall-through
1012 
1013  case 0x08: // CSM/KEY BOARD SPLIT/-/-/SAMPLE/DA AD/64K/ROM
1014  case 0x09: // START ADDRESS (L)
1015  case 0x0A: // START ADDRESS (H)
1016  case 0x0B: // STOP ADDRESS (L)
1017  case 0x0C: // STOP ADDRESS (H)
1018  case 0x0D: // PRESCALE (L)
1019  case 0x0E: // PRESCALE (H)
1020  case 0x0F: // ADPCM-DATA
1021  case 0x10: // DELTA-N (L)
1022  case 0x11: // DELTA-N (H)
1023  case 0x12: // ENVELOP CONTROL
1024  case 0x1A: // PCM-DATA
1025  reg[rg] = data;
1026  adpcm.writeReg(rg, data, time);
1027  break;
1028 
1029  case 0x15: // DAC-DATA (bit9-2)
1030  reg[rg] = data;
1031  if (reg[0x08] & 0x04) {
1032  int tmp = static_cast<signed char>(reg[0x15]) * 256
1033  + reg[0x16];
1034  tmp = (tmp * 4) >> (7 - reg[0x17]);
1035  tmp = Math::clipIntToShort(tmp);
1036  dac13.writeDAC(tmp, time);
1037  }
1038  break;
1039  case 0x16: // (bit1-0)
1040  reg[rg] = data & 0xC0;
1041  break;
1042  case 0x17: // (exponent)
1043  reg[rg] = data & 0x07;
1044  break;
1045 
1046  case 0x18: // I/O-CONTROL (bit3-0)
1047  // 0 -> input
1048  // 1 -> output
1049  reg[rg] = data;
1050  periphery.write(reg[0x18], reg[0x19], time);
1051  break;
1052 
1053  case 0x19: // I/O-DATA (bit3-0)
1054  reg[rg] = data;
1055  periphery.write(reg[0x18], reg[0x19], time);
1056  break;
1057  }
1058  break;
1059  }
1060  case 0x20: {
1061  int s = stbl[rg & 0x1f];
1062  if (s >= 0) {
1063  auto& chan = ch[s / 2];
1064  auto& slot = chan.slot[s & 1];
1065  slot.patch.AM = (data >> 7) & 1;
1066  slot.patch.PM = (data >> 6) & 1;
1067  slot.patch.EG = (data >> 5) & 1;
1068  slot.patch.setKeyScaleRate((data & 0x10) != 0);
1069  slot.patch.ML = (data >> 0) & 15;
1070  slot.updateAll(chan.freq);
1071  }
1072  reg[rg] = data;
1073  break;
1074  }
1075  case 0x40: {
1076  int s = stbl[rg & 0x1f];
1077  if (s >= 0) {
1078  auto& chan = ch[s / 2];
1079  auto& slot = chan.slot[s & 1];
1080  slot.patch.KL = (data >> 6) & 3;
1081  slot.patch.TL = (data >> 0) & 63;
1082  slot.updateAll(chan.freq);
1083  }
1084  reg[rg] = data;
1085  break;
1086  }
1087  case 0x60: {
1088  int s = stbl[rg & 0x1f];
1089  if (s >= 0) {
1090  auto& slot = ch[s / 2].slot[s & 1];
1091  slot.patch.AR = (data >> 4) & 15;
1092  slot.patch.DR = (data >> 0) & 15;
1093  slot.updateEG();
1094  }
1095  reg[rg] = data;
1096  break;
1097  }
1098  case 0x80: {
1099  int s = stbl[rg & 0x1f];
1100  if (s >= 0) {
1101  auto& slot = ch[s / 2].slot[s & 1];
1102  slot.patch.SL = (data >> 4) & 15;
1103  slot.patch.RR = (data >> 0) & 15;
1104  slot.updateEG();
1105  }
1106  reg[rg] = data;
1107  break;
1108  }
1109  case 0xa0: {
1110  if (rg == 0xbd) {
1111  am_mode = (data & 0x80) != 0;
1112  pm_mode = (data & 0x40) != 0;
1113 
1114  setRythmMode(data);
1115  if (rythm_mode) {
1116  if (data & 0x10) keyOn_BD(); else keyOff_BD();
1117  if (data & 0x08) keyOn_SD(); else keyOff_SD();
1118  if (data & 0x04) keyOn_TOM(); else keyOff_TOM();
1119  if (data & 0x02) keyOn_CYM(); else keyOff_CYM();
1120  if (data & 0x01) keyOn_HH(); else keyOff_HH();
1121  }
1122  ch[6].slot[MOD].updateAll(ch[6].freq);
1123  ch[6].slot[CAR].updateAll(ch[6].freq);
1124  ch[7].slot[MOD].updateAll(ch[7].freq);
1125  ch[7].slot[CAR].updateAll(ch[7].freq);
1126  ch[8].slot[MOD].updateAll(ch[8].freq);
1127  ch[8].slot[CAR].updateAll(ch[8].freq);
1128 
1129  reg[rg] = data;
1130  break;
1131  }
1132  unsigned c = rg & 0x0f;
1133  if (c > 8) {
1134  // 0xa9-0xaf 0xb9-0xbf
1135  break;
1136  }
1137  unsigned freq;
1138  if (!(rg & 0x10)) {
1139  // 0xa0-0xa8
1140  freq = data | ((reg[rg + 0x10] & 0x1F) << 8);
1141  } else {
1142  // 0xb0-0xb8
1143  if (data & 0x20) {
1144  ch[c].keyOn (KEY_MAIN);
1145  } else {
1146  ch[c].keyOff(KEY_MAIN);
1147  }
1148  freq = reg[rg - 0x10] | ((data & 0x1F) << 8);
1149  }
1150  ch[c].setFreq(freq);
1151  unsigned fNum = freq % 1024;
1152  unsigned block = freq / 1024;
1153  switch (c) {
1154  case 7: noiseA_dphase = fNum << block;
1155  break;
1156  case 8: noiseB_dphase = fNum << block;
1157  break;
1158  }
1159  ch[c].slot[CAR].updateAll(freq);
1160  ch[c].slot[MOD].updateAll(freq);
1161  reg[rg] = data;
1162  break;
1163  }
1164  case 0xc0: {
1165  if (rg > 0xc8)
1166  break;
1167  int c = rg - 0xC0;
1168  ch[c].slot[MOD].patch.setFeedbackShift((data >> 1) & 7);
1169  ch[c].alg = data & 1;
1170  reg[rg] = data;
1171  }
1172  }
1173 }
1174 
1175 byte Y8950::readReg(byte rg, EmuTime::param time)
1176 {
1177  updateStream(time); // TODO only when necessary
1178 
1179  byte result;
1180  switch (rg) {
1181  case 0x0F: // ADPCM-DATA
1182  case 0x13: // ???
1183  case 0x14: // ???
1184  case 0x1A: // PCM-DATA
1185  result = adpcm.readReg(rg, time);
1186  break;
1187  default:
1188  result = peekReg(rg, time);
1189  }
1190  return result;
1191 }
1192 
1193 byte Y8950::peekReg(byte rg, EmuTime::param time) const
1194 {
1195  switch (rg) {
1196  case 0x05: // (KEYBOARD IN)
1197  return connector.peek(time);
1198 
1199  case 0x0F: // ADPCM-DATA
1200  case 0x13: // ???
1201  case 0x14: // ???
1202  case 0x1A: // PCM-DATA
1203  return adpcm.peekReg(rg, time);
1204 
1205  case 0x19: { // I/O DATA
1206  byte input = periphery.read(time);
1207  byte output = reg[0x19];
1208  byte enable = reg[0x18];
1209  return (output & enable) | (input & ~enable) | 0xF0;
1210  }
1211  default:
1212  return reg[rg];
1213  }
1214 }
1215 
1216 byte Y8950::readStatus(EmuTime::param time)
1217 {
1218  byte result = peekStatus(time);
1219  //std::cout << "status: " << (int)result << '\n';
1220  return result;
1221 }
1222 
1223 byte Y8950::peekStatus(EmuTime::param time) const
1224 {
1225  const_cast<Y8950Adpcm&>(adpcm).sync(time);
1226  return (status & (0x87 | statusMask)) | 0x06; // bit 1 and 2 are always 1
1227 }
1228 
1229 void Y8950::callback(byte flag)
1230 {
1231  setStatus(flag);
1232 }
1233 
1235 {
1236  status |= flags;
1237  if (status & statusMask) {
1238  status |= 0x80;
1239  irq.set();
1240  }
1241 }
1243 {
1244  status &= ~flags;
1245  if (!(status & statusMask)) {
1246  status &= 0x7f;
1247  irq.reset();
1248  }
1249 }
1251 {
1252  return status;
1253 }
1254 void Y8950::changeStatusMask(byte newMask)
1255 {
1256  statusMask = newMask;
1257  status &= 0x87 | statusMask;
1258  if (status & statusMask) {
1259  status |= 0x80;
1260  irq.set();
1261  } else {
1262  status &= 0x7f;
1263  irq.reset();
1264  }
1265 }
1266 
1267 
1268 template<typename Archive>
1269 void Y8950::Patch::serialize(Archive& ar, unsigned /*version*/)
1270 {
1271  ar.serialize("AM", AM);
1272  ar.serialize("PM", PM);
1273  ar.serialize("EG", EG);
1274  ar.serialize("KR", KR);
1275  ar.serialize("ML", ML);
1276  ar.serialize("KL", KL);
1277  ar.serialize("TL", TL);
1278  ar.serialize("FB", FB);
1279  ar.serialize("AR", AR);
1280  ar.serialize("DR", DR);
1281  ar.serialize("SL", SL);
1282  ar.serialize("RR", RR);
1283 }
1284 
1285 static std::initializer_list<enum_string<Y8950::EnvelopeState>> envelopeStateInfo = {
1286  { "ATTACK", Y8950::ATTACK },
1287  { "DECAY", Y8950::DECAY },
1288  { "SUSTAIN", Y8950::SUSTAIN },
1289  { "RELEASE", Y8950::RELEASE },
1290  { "FINISH", Y8950::FINISH }
1291 };
1292 SERIALIZE_ENUM(Y8950::EnvelopeState, envelopeStateInfo);
1293 
1294 // version 1: initial version
1295 // version 2: 'slotStatus' is replaced with 'key' and no longer serialized
1296 // instead it's recalculated via update_key_status()
1297 // version 3: serialize 'eg_mode' as an enum instead of an int, also merged
1298 // the 2 enum values SUSHOLD and SUSTINE into SUSTAIN
1299 template<typename Archive>
1300 void Y8950::Slot::serialize(Archive& ar, unsigned version)
1301 {
1302  ar.serialize("feedback", feedback);
1303  ar.serialize("output", output);
1304  ar.serialize("phase", phase);
1305  ar.serialize("eg_phase", eg_phase);
1306  ar.serialize("patch", patch);
1307  if (ar.versionAtLeast(version, 3)) {
1308  ar.serialize("eg_mode", eg_mode);
1309  } else {
1310  assert(ar.isLoader());
1311  int tmp = 0; // dummy init to avoid warning
1312  ar.serialize("eg_mode", tmp);
1313  switch (tmp) {
1314  case 0: eg_mode = ATTACK; break;
1315  case 1: eg_mode = DECAY; break;
1316  case 2: eg_mode = SUSTAIN; break; // was SUSHOLD
1317  case 3: eg_mode = SUSTAIN; break; // was SUSTINE
1318  case 4: eg_mode = RELEASE; break;
1319  default: eg_mode = FINISH; break;
1320  }
1321  }
1322 
1323  // These are restored by call to updateAll() in Y8950::Channel::serialize()
1324  // dphase, tll, dphaseARTableRks, dphaseDRTableRks, eg_dphase
1325  // These are restored by update_key_status():
1326  // key
1327 }
1328 
1329 template<typename Archive>
1330 void Y8950::Channel::serialize(Archive& ar, unsigned /*version*/)
1331 {
1332  ar.serialize("mod", slot[MOD]);
1333  ar.serialize("car", slot[CAR]);
1334  ar.serialize("freq", freq);
1335  ar.serialize("alg", alg);
1336 
1337  if (ar.isLoader()) {
1338  slot[MOD].updateAll(freq);
1339  slot[CAR].updateAll(freq);
1340  }
1341 }
1342 
1343 template<typename Archive>
1344 void Y8950::serialize(Archive& ar, unsigned /*version*/)
1345 {
1346  ar.serialize("keyboardConnector", connector);
1347  ar.serialize("adpcm", adpcm);
1348  ar.serialize("timer1", *timer1);
1349  ar.serialize("timer2", *timer2);
1350  ar.serialize("irq", irq);
1351  ar.serialize_blob("registers", reg, sizeof(reg));
1352  ar.serialize("pm_phase", pm_phase);
1353  ar.serialize("am_phase", am_phase);
1354  ar.serialize("noise_seed", noise_seed);
1355  ar.serialize("noiseA_phase", noiseA_phase);
1356  ar.serialize("noiseB_phase", noiseB_phase);
1357  ar.serialize("noiseA_dphase", noiseA_dphase);
1358  ar.serialize("noiseB_dphase", noiseB_dphase);
1359  ar.serialize("channels", ch);
1360  ar.serialize("status", status);
1361  ar.serialize("statusMask", statusMask);
1362  ar.serialize("rythm_mode", rythm_mode);
1363  ar.serialize("am_mode", am_mode);
1364  ar.serialize("pm_mode", pm_mode);
1365  ar.serialize("enabled", enabled);
1366 
1367  // TODO restore more state from registers
1368  static const byte rewriteRegs[] = {
1369  6, // connector
1370  15, // dac13
1371  };
1372  if (ar.isLoader()) {
1373  update_key_status();
1374  EmuTime::param time = motherBoard.getCurrentTime();
1375  for (auto r : rewriteRegs) {
1376  writeReg(r, reg[r], time);
1377  }
1378  }
1379 }
1380 
1381 
1382 // SimpleDebuggable
1383 
1384 Y8950::Debuggable::Debuggable(MSXMotherBoard& motherBoard_,
1385  const std::string& name_)
1386  : SimpleDebuggable(motherBoard_, name_ + " regs", "MSX-AUDIO", 0x100)
1387 {
1388 }
1389 
1390 byte Y8950::Debuggable::read(unsigned address, EmuTime::param time)
1391 {
1392  auto& y8950 = OUTER(Y8950, debuggable);
1393  return y8950.peekReg(address, time);
1394 }
1395 
1396 void Y8950::Debuggable::write(unsigned address, byte value, EmuTime::param time)
1397 {
1398  auto& y8950 = OUTER(Y8950, debuggable);
1399  y8950.writeReg(address, value, time);
1400 }
1401 
1403 SERIALIZE_CLASS_VERSION(Y8950::Slot, 3);
1404 
1405 } // namespace openmsx
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
byte peekReg(byte rg, EmuTime::param time) const
Definition: Y8950Adpcm.cc:304
static constexpr int CLOCK_FREQ_DIV
Definition: Y8950.hh:27
FixedPoint< EG_DP_BITS - EG_BITS > EnvPhaseIndex
Definition: Y8950.hh:105
unsigned table[PG_WIDTH]
Definition: Y8950.cc:248
virtual nibble read(EmuTime::param time)=0
Read from (some of) the pins Some of the pins might be programmed as output, but this method doesn&#39;t ...
byte readReg(byte rg, EmuTime::param time)
Definition: Y8950Adpcm.cc:295
void reset(EmuTime::param time)
Definition: Y8950Adpcm.cc:62
vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:269
void resetStatus(byte flags)
Definition: Y8950.cc:1242
void setEnabled(bool enabled, EmuTime::param time)
Definition: Y8950.cc:807
static constexpr int R04_IRQ_RESET
Definition: Y8950.hh:45
void unregisterSound()
Unregisters this sound device with the Mixer.
Definition: SoundDevice.cc:130
void reset(EmuTime::param time)
Definition: Y8950.cc:586
#define M_PI
Definition: Math.hh:27
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
byte readStatus(EmuTime::param time)
Definition: Y8950.cc:1216
Y8950(const std::string &name, const DeviceConfig &config, unsigned sampleRam, EmuTime::param time, MSXAudio &audio)
Definition: Y8950.cc:508
static constexpr int EG_BITS
Definition: Y8950.hh:101
byte peek(EmuTime::param time) const
void fill(ForwardRange &&range, const T &value)
Definition: ranges.hh:179
int16_t clipIntToShort(int x)
Clip x to range [-32768,32767].
Definition: Math.hh:58
void updateStream(EmuTime::param time)
Definition: SoundDevice.cc:135
constexpr auto data(C &c) -> decltype(c.data())
Definition: span.hh:69
byte peekReg(byte rg, EmuTime::param time) const
Definition: Y8950.cc:1193
int tab[(2 *DB_MUTE) *2]
Definition: Y8950.cc:208
static constexpr int R04_ST2
Definition: Y8950.hh:33
bool isMuted() const
Definition: Y8950Adpcm.cc:88
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
void setInputRate(unsigned sampleRate)
Definition: SoundDevice.hh:111
#define S2E(x)
Definition: Y8950.cc:686
virtual void setSPOFF(bool value, EmuTime::param time)
SP-OFF bit (bit 3 in Y8950 register 7)
void clearRam()
Definition: Y8950.cc:580
int table[2][PM_PG_WIDTH]
Definition: Y8950.cc:268
static constexpr int CLOCK_FREQ
Definition: Y8950.hh:26
void write(byte data, EmuTime::param time)
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
void reset()
Reset the interrupt request on the bus.
Definition: IRQHelper.hh:97
void writeReg(byte rg, byte data, EmuTime::param time)
Definition: Y8950.cc:932
int main(int argc, char **argv)
Definition: main.cc:137
#define ML(x)
byte peekStatus(EmuTime::param time) const
Definition: Y8950.cc:1223
unsigned ar[EG_MUTE]
Definition: Y8950.cc:178
void set()
Set the interrupt request on the bus.
Definition: IRQHelper.hh:88
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:840
unsigned ra[EG_MUTE+1]
Definition: Y8950.cc:179
byte readReg(byte rg, EmuTime::param time)
Definition: Y8950.cc:1175
void serialize(Archive &ar, unsigned version)
Definition: Y8950.cc:1344
void writeReg(byte rg, byte data, EmuTime::param time)
Definition: Y8950Adpcm.cc:150
EmuTime::param getCurrentTime()
Convenience method: This is the same as getScheduler().getCurrentTime().
const string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:572
#define OUTER(type, member)
Definition: outer.hh:38
byte peekRawStatus() const
Definition: Y8950.cc:1250
Y8950::EnvPhaseIndex table[16][16]
Definition: Y8950.cc:313
void serialize(Archive &ar, T &t, unsigned version)
virtual void write(nibble outputs, nibble values, EmuTime::param time)=0
Write to (some of) the pins.
void setStatus(byte flags)
Definition: Y8950.cc:1234
int table[16 *8][4]
Definition: Y8950.cc:284
void writeDAC(int16_t value, EmuTime::param time)
Definition: DACSound16S.cc:32
void registerSound(const DeviceConfig &config)
Registers this sound device with the Mixer.
Definition: SoundDevice.cc:89
static constexpr int R04_ST1
Definition: Y8950.hh:31