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