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