]> Shamusworld >> Repos - apple2/blob - src/ay8910.cpp
cfb293d8e5528159d17affe85c12afd88b5e0468
[apple2] / src / ay8910.cpp
1 // AY-3-8910 Emulator
2 //
3 // This was written mainly from the General Instruments datasheet for the 8910
4 // part.  I would have used the one from MAME, but it was so poorly written and
5 // so utterly incomprehensible that I decided to start from scratch to see if I
6 // could do any better; and so here we are.  I did use a bit of code from
7 // MAME's AY-3-8910 RNG, as it was just too neat not to use.  :-)
8 //
9 // by James Hammons
10 // (C) 2018 Underground Software
11 //
12
13 #include "ay8910.h"
14
15 #include <string.h>                     // for memset()
16 #include "log.h"
17 #include "sound.h"
18
19
20 struct AY_3_8910
21 {
22         // User visible registers
23         uint16_t period[3];             // Channel A-C period
24         int16_t volume[3];              // Channel A-C volume (non-envelope mode)
25         bool envEnable[3];              // Channel A-C envelope enable
26         bool toneEnable[3];             // Channel A-C tone enable
27         bool noiseEnable[3];    // Channel A-C noise enable
28         uint16_t noisePeriod;   // Noise period (5 bits * 16)
29         uint32_t envPeriod;             // Envelope period (16 bits * 256)
30         bool envAttack;                 // Envelope Attack bit
31         bool envAlternate;              // Envelope Alternate bit
32         bool envHold;                   // Envelope Hold bit
33         // Internal registers
34         uint16_t count[3];              // Channel A-C current count
35         bool state[3];                  // Channel A-C current state
36         uint16_t noiseCount;    // Noise current count
37         bool noiseState;                // Noise state
38         uint32_t envCount[3];   // Envelope current count
39         int16_t envDirection[3];// Envelope direction (rising, 0, or falling)
40         uint32_t prng;                  // Psuedo RNG (17 bits)
41 };
42
43
44 // Maximum volume that can be generated by one voice
45 float maxVolume = 8192.0f;
46
47 // Normalized volumes (zero to one) for AY-3-8910 output, in 16 steps
48 static float normalizedVolume[16];// = {};
49
50 // AY-3-8910 register IDs
51 enum { AY_AFINE = 0, AY_ACOARSE, AY_BFINE, AY_BCOARSE, AY_CFINE, AY_CCOARSE,
52         AY_NOISEPER, AY_ENABLE, AY_AVOL, AY_BVOL, AY_CVOL, AY_EFINE, AY_ECOARSE,
53         AY_ESHAPE, AY_PORTA, AY_PORTB };
54
55 // Chip structs (for up to four separate chips)
56 static AY_3_8910 ay[4];
57
58
59 void AYInit(void)
60 {
61         for(int chip=0; chip<4; chip++)
62                 AYReset(chip);
63
64         // Our normalized volume levels are from 0 to -48 dB, in 3 dB steps.
65         // N.B.: It's 3dB steps because those sound the best.  Dunno what it really
66         //       is, as nothing in the documentation tells you (it only says that
67         //       each channel's volume is normalized from 0 to 1.0V).
68         float level = 1.0f;
69
70         for(int i=15; i>=0; i--)
71         {
72                 normalizedVolume[i] = level;
73                 level /= 1.4125375446228;       // 10.0 ^ (3.0 / 20.0) = 3 dB
74         }
75
76         // In order to get a scale that goes from 0 to 1 smoothly, we renormalize
77         // our volumes so that volume[0] is actually 0, and volume[15] is 1.
78         // Basically, we're sliding the curve down the Y-axis so that volume[0]
79         // touches the X-axis, then stretching the result so that it fits into the
80         // interval (0, 1).
81         float vol0 = normalizedVolume[0];
82         float vol15 = normalizedVolume[15] - vol0;
83
84         for(int i=0; i<16; i++)
85                 normalizedVolume[i] = (normalizedVolume[i] - vol0) / vol15;
86
87 #if 0
88         WriteLog("\nRenormalized volume, level (max=%d):\n", (int)maxVolume);
89         for(int i=0; i<16; i++)
90                 WriteLog("%lf, %d\n", normalizedVolume[i], (int)(normalizedVolume[i] * maxVolume));
91         WriteLog("\n");
92 #endif
93 }
94 /*
95 Renormalized:
96 0.000000, 0
97 0.002333, 13
98 0.005628, 33
99 0.010283, 61
100 0.016859, 101
101 0.026146, 156
102 0.039266, 235
103 0.057797, 346
104 0.083974, 503
105 0.120949, 725
106 0.173178, 1039
107 0.246954, 1481
108 0.351165, 2106
109 0.498366, 2990
110 0.706294, 4237
111 1.000000, 6000
112 */
113
114
115 void AYReset(int chipNum)
116 {
117         memset(&ay[chipNum], 0, sizeof(struct AY_3_8910));
118         ay[chipNum].prng = 1;   // Set correct PRNG seed
119 }
120
121
122 void AYWrite(int chipNum, int reg, int value)
123 {
124 #if 0
125 static char regname[16][32] = {
126         "AY_AFINE   ",
127         "AY_ACOARSE ",
128         "AY_BFINE   ",
129         "AY_BCOARSE ",
130         "AY_CFINE   ",
131         "AY_CCOARSE ",
132         "AY_NOISEPER",
133         "AY_ENABLE  ",
134         "AY_AVOL    ",
135         "AY_BVOL    ",
136         "AY_CVOL    ",
137         "AY_EFINE   ",
138         "AY_ECOARSE ",
139         "AY_ESHAPE  ",
140         "AY_PORTA   ",
141         "AY_PORTB   "
142 };
143 WriteLog("*** AY(%d) Reg: %s = $%02X\n", chipNum, regname[reg], value);
144 #endif
145         AY_3_8910 * chip = &ay[chipNum];
146         value &= 0xFF;  // Ensure passed in value is no larger than 8 bits
147
148         switch (reg)
149         {
150         case AY_AFINE:
151                 // The square wave period is the passed in value times 16, so we handle
152                 // that here.
153                 chip->period[0] = (chip->period[0] & 0xF000) | (value << 4);
154                 break;
155         case AY_ACOARSE:
156                 chip->period[0] = ((value & 0x0F) << 12) | (chip->period[0] & 0xFF0);
157                 break;
158         case AY_BFINE:
159                 chip->period[1] = (chip->period[1] & 0xF000) | (value << 4);
160                 break;
161         case AY_BCOARSE:
162                 chip->period[1] = ((value & 0x0F) << 12) | (chip->period[1] & 0xFF0);
163                 break;
164         case AY_CFINE:
165                 chip->period[2] = (chip->period[2] & 0xF000) | (value << 4);
166                 break;
167         case AY_CCOARSE:
168                 chip->period[2] = ((value & 0x0F) << 12) | (chip->period[2] & 0xFF0);
169                 break;
170         case AY_NOISEPER:
171                 // Like the square wave period, the value is the what's passed * 16.
172                 chip->noisePeriod = (value & 0x1F) << 4;
173                 break;
174         case AY_ENABLE:
175                 chip->toneEnable[0] = (value & 0x01 ? false : true);
176                 chip->toneEnable[1] = (value & 0x02 ? false : true);
177                 chip->toneEnable[2] = (value & 0x04 ? false : true);
178                 chip->noiseEnable[0] = (value & 0x08 ? false : true);
179                 chip->noiseEnable[1] = (value & 0x10 ? false : true);
180                 chip->noiseEnable[2] = (value & 0x20 ? false : true);
181                 break;
182         case AY_AVOL:
183                 chip->volume[0]    = value & 0x0F;
184                 chip->envEnable[0] = (value & 0x10 ? true : false);
185
186                 if (chip->envEnable[0])
187                 {
188                         chip->envCount[0]     = 0;
189                         chip->volume[0]       = (chip->envAttack ? 0 : 15);
190                         chip->envDirection[0] = (chip->envAttack ? 1 : -1);
191                 }
192                 break;
193         case AY_BVOL:
194                 chip->volume[1]    = value & 0x0F;
195                 chip->envEnable[1] = (value & 0x10 ? true : false);
196
197                 if (chip->envEnable[1])
198                 {
199                         chip->envCount[1]     = 0;
200                         chip->volume[1]       = (chip->envAttack ? 0 : 15);
201                         chip->envDirection[1] = (chip->envAttack ? 1 : -1);
202                 }
203                 break;
204         case AY_CVOL:
205                 chip->volume[2]    = value & 0x0F;
206                 chip->envEnable[2] = (value & 0x10 ? true : false);
207
208                 if (chip->envEnable[2])
209                 {
210                         chip->envCount[2]     = 0;
211                         chip->volume[2]       = (chip->envAttack ? 0 : 15);
212                         chip->envDirection[2] = (chip->envAttack ? 1 : -1);
213                 }
214                 break;
215         case AY_EFINE:
216                 // The envelope period is 256 times the passed in value
217                 chip->envPeriod = (chip->envPeriod & 0xFF0000) | (value << 8);
218                 break;
219         case AY_ECOARSE:
220                 chip->envPeriod = (value << 16) | (chip->envPeriod & 0xFF00);
221                 break;
222         case AY_ESHAPE:
223                 chip->envAttack    = (value & 0x04 ? true : false);
224                 chip->envAlternate = (value & 0x02 ? true : false);
225                 chip->envHold      = (value & 0x01 ? true : false);
226
227                 // If the Continue bit is *not* set, the Alternate bit is forced to the
228                 // Attack bit, and Hold is forced on.
229                 if (!(value & 0x08))
230                 {
231                         chip->envAlternate = chip->envAttack;
232                         chip->envHold = true;
233                 }
234
235                 // Reset all voice envelope counts...
236                 for(int i=0; i<3; i++)
237                 {
238                         chip->envCount[i]     = 0;
239                         chip->envDirection[i] = (chip->envAttack ? 1 : -1);
240
241                         // Only reset the volume if the envelope is enabled!
242                         if (chip->envEnable[i])
243                                 chip->volume[i] = (chip->envAttack ? 0 : 15);
244                 }
245                 break;
246         }
247 }
248
249
250 //
251 // Generate one sample and quit
252 //
253 bool logAYInternal = false;
254 uint16_t AYGetSample(int chipNum)
255 {
256         AY_3_8910 * chip = &ay[chipNum];
257         uint16_t sample = 0;
258
259         // Number of cycles per second to run the PSG is the 6502 clock rate
260         // divided by the host sample rate
261         const static double exactCycles = 1020484.32 / (double)SAMPLE_RATE;
262         static double overflow = 0;
263
264         int fullCycles = (int)exactCycles;
265         overflow += exactCycles - (double)fullCycles;
266
267         if (overflow >= 1.0)
268         {
269                 fullCycles++;
270                 overflow -= 1.0;
271         }
272
273         for(int i=0; i<fullCycles; i++)
274         {
275                 for(int j=0; j<3; j++)
276                 {
277                         // Tone generators only run if the corresponding voice is enabled.
278                         // N.B.: We also reject any period set that is less than 2.
279                         if (chip->toneEnable[j] && (chip->period[j] > 16))
280                         {
281                                 chip->count[j]++;
282
283                                 // It's (period / 2) because one full period of a square wave
284                                 // is 0 for half of its period and 1 for the other half!
285                                 if (chip->count[j] > (chip->period[j] / 2))
286                                 {
287                                         chip->count[j] = 0;
288                                         chip->state[j] = !chip->state[j];
289                                 }
290                         }
291
292                         // Envelope generator only runs if the corresponding voice flag is
293                         // enabled.
294                         if (chip->envEnable[j])
295                         {
296                                 chip->envCount[j]++;
297
298                                 // It's (EP / 16) because there are 16 volume steps in each EP.
299                                 if (chip->envCount[j] > (chip->envPeriod / 16))
300                                 {
301                                         // Attack 0 = \, 1 = / (attack lasts one EP)
302                                         // Alternate = mirror envelope's last attack
303                                         // Hold = run 1 EP, hold at level (Alternate XOR Attack)
304                                         chip->envCount[j] = 0;
305
306                                         // We've hit a point where we need to make a change to the
307                                         // envelope's volume, so do it:
308                                         chip->volume[j] += chip->envDirection[j];
309
310                                         // If we hit the end of the EP, change the state of the
311                                         // envelope according to the envelope's variables.
312                                         if ((chip->volume[j] > 15) || (chip->volume[j] < 0))
313                                         {
314                                                 // Hold means we set the volume to (Alternate XOR
315                                                 // Attack) and stay there after the Attack EP.
316                                                 if (chip->envHold)
317                                                 {
318                                                         chip->volume[j] = (chip->envAttack != chip->envAlternate ? 15: 0);
319                                                         chip->envDirection[j] = 0;
320                                                 }
321                                                 else
322                                                 {
323                                                         // If the Alternate bit is set, we mirror the
324                                                         // Attack pattern; otherwise we reset it to the
325                                                         // whatever level was set by the Attack bit.
326                                                         if (chip->envAlternate)
327                                                         {
328                                                                 chip->envDirection[j] = -chip->envDirection[j];
329                                                                 chip->volume[j] += chip->envDirection[j];
330                                                         }
331                                                         else
332                                                                 chip->volume[j] = (chip->envAttack ? 0 : 15);
333                                                 }
334                                         }
335                                 }
336                         }
337                 }
338
339                 // Noise generator (the PRNG) runs all the time:
340                 chip->noiseCount++;
341
342                 if (chip->noiseCount > chip->noisePeriod)
343                 {
344                         chip->noiseCount = 0;
345
346                         // The following is from MAME's AY-3-8910 code:
347                         // The Pseudo Random Number Generator of the 8910 is a 17-bit shift
348                         // register. The input to the shift register is bit0 XOR bit3 (bit0
349                         // is the output). This was verified on AY-3-8910 and YM2149 chips.
350
351                         // The following is a fast way to compute bit17 = bit0 ^ bit3.
352                         // Instead of doing all the logic operations, we only check bit0,
353                         // relying on the fact that after three shifts of the register,
354                         // what now is bit3 will become bit0, and will invert, if
355                         // necessary, bit14, which previously was bit17.
356                         if (chip->prng & 0x00001)
357                         {
358                                 // This version is called the "Galois configuration".
359                                 chip->prng ^= 0x24000;
360                                 // The noise wave *toggles* when a one shows up in bit0...
361                                 chip->noiseState = !chip->noiseState;
362                         }
363
364                         chip->prng >>= 1;
365                 }
366         }
367
368         // We mix channels A-C here into one sample, because the Mockingboard just
369         // sums the output of the AY-3-8910 by tying their lines together.
370         // We also handle the various cases (of which there are four) of mixing
371         // pure tones and "noise" tones together.
372         for(int i=0; i<3; i++)
373         {
374                 // Set the volume level scaled by the maximum volume (which can be
375                 // altered outside of this module).
376                 int level = (int)(normalizedVolume[chip->volume[i]] * maxVolume);
377
378                 if (chip->toneEnable[i] && !chip->noiseEnable[i])
379                         sample += (chip->state[i] ? level : 0);
380                 else if (!chip->toneEnable[i] && chip->noiseEnable[i])
381                         sample += (chip->noiseState ? level : 0);
382                 else if (chip->toneEnable[i] && chip->noiseEnable[i])
383                         sample += (chip->state[i] & chip->noiseState ? level : 0);
384                 else if (!chip->toneEnable[i] && !chip->noiseEnable[i])
385                         sample += level;
386         }
387
388         if (logAYInternal)
389         {
390                 WriteLog("    (%d) State A,B,C: %s %s %s, Sample: $%04X, P: $%X, $%X, $%X\n", chipNum, (chip->state[0] ? "1" : "0"), (chip->state[1] ? "1" : "0"), (chip->state[2] ? "1" : "0"), sample, chip->period[0], chip->period[1], chip->period[2]);
391         }
392
393         return sample;
394 }
395
396
397
398
399
400 // STUFF TO DELETE...
401
402 #if 0
403
404 /***************************************************************************
405
406   ay8910.cpp
407
408   Emulation of the AY-3-8910 / YM2149 sound chip.
409
410   Based on various code snippets by Ville Hallik, Michael Cuddy,
411   Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria.
412
413 ***************************************************************************/
414
415 //
416 // From mame.txt (http://www.mame.net/readme.html)
417 //
418 // VI. Reuse of Source Code
419 // --------------------------
420 //    This chapter might not apply to specific portions of MAME (e.g. CPU
421 //    emulators) which bear different copyright notices.
422 //    The source code cannot be used in a commercial product without the
423 //    written authorization of the authors. Use in non-commercial products is
424 //    allowed, and indeed encouraged.  If you use portions of the MAME source
425 //    code in your program, however, you must make the full source code freely
426 //    available as well.
427 //    Usage of the _information_ contained in the source code is free for any
428 //    use. However, given the amount of time and energy it took to collect this
429 //    information, if you find new information we would appreciate if you made
430 //    it freely available as well.
431 //
432
433 // JLH: Commented out MAME specific crap
434
435 #define MAX_OUTPUT 0x7FFF
436
437 // See AY8910_set_clock() for definition of STEP
438 #define STEP 0x8000
439
440 struct AY8910
441 {
442         int Channel;
443         int SampleRate;
444         int register_latch;
445         unsigned char Regs[16];
446         unsigned int UpdateStep;
447         int PeriodA, PeriodB, PeriodC, PeriodN, PeriodE;
448         int CountA, CountB, CountC, CountN, CountE;
449         unsigned int VolA, VolB, VolC, VolE;
450         unsigned char EnvelopeA, EnvelopeB, EnvelopeC;
451         unsigned char OutputA, OutputB, OutputC, OutputN;
452         signed char CountEnv;
453         unsigned char Hold, Alternate, Attack, Holding;
454         int RNG;
455         unsigned int VolTable[32];
456 };
457
458 static struct AY8910 AYPSG[MAX_8910];           /* array of PSG's */
459
460 #define AY_AFINE        (0)
461 #define AY_ACOARSE      (1)
462 #define AY_BFINE        (2)
463 #define AY_BCOARSE      (3)
464 #define AY_CFINE        (4)
465 #define AY_CCOARSE      (5)
466 #define AY_NOISEPER     (6)
467 #define AY_ENABLE       (7)
468 #define AY_AVOL         (8)
469 #define AY_BVOL         (9)
470 #define AY_CVOL         (10)
471 #define AY_EFINE        (11)
472 #define AY_ECOARSE      (12)
473 #define AY_ESHAPE       (13)
474 //#define AY_PORTA      (14)
475 //#define AY_PORTB      (15)
476
477
478 void _AYWriteReg(int n, int r, int v)
479 {
480 #if 1
481 static char regname[16][32] = {
482 "AY_AFINE   ",
483 "AY_ACOARSE ",
484 "AY_BFINE   ",
485 "AY_BCOARSE ",
486 "AY_CFINE   ",
487 "AY_CCOARSE ",
488 "AY_NOISEPER",
489 "AY_ENABLE  ",
490 "AY_AVOL    ",
491 "AY_BVOL    ",
492 "AY_CVOL    ",
493 "AY_EFINE   ",
494 "AY_ECOARSE ",
495 "AY_ESHAPE  ",
496 "AY_PORTA   ",
497 "AY_PORTB   "
498 };
499 WriteLog("*** AY(%d) Reg: %s = $%02X\n", n, regname[r], v);
500 #endif
501         struct AY8910 * PSG = &AYPSG[n];
502         int old;
503
504         PSG->Regs[r] = v;
505
506         /* A note about the period of tones, noise and envelope: for speed reasons,
507          * we count down from the period to 0, but careful studies of the chip
508          * output prove that it instead counts up from 0 until the counter becomes
509          * greater or equal to the period. This is an important difference when the
510          * program is rapidly changing the period to modulate the sound.
511          * To compensate for the difference, when the period is changed we adjust
512          * our internal counter.
513          * Also, note that period = 0 is the same as period = 1. This is mentioned
514          * in the YM2203 data sheets. However, this does NOT apply to the Envelope
515          * period. In that case, period = 0 is half as period = 1.                  */
516         switch (r)
517         {
518         case AY_AFINE:
519         case AY_ACOARSE:
520                 PSG->Regs[AY_ACOARSE] &= 0x0F;
521                 old = PSG->PeriodA;
522 //              PSG->PeriodA = (PSG->Regs[AY_AFINE] + 256 * PSG->Regs[AY_ACOARSE]) * PSG->UpdateStep;
523                 PSG->PeriodA = ((PSG->Regs[AY_ACOARSE] << 8) | PSG->Regs[AY_AFINE]) * PSG->UpdateStep;
524
525                 if (PSG->PeriodA == 0)
526                         PSG->PeriodA = PSG->UpdateStep;
527
528                 PSG->CountA += PSG->PeriodA - old;
529
530                 if (PSG->CountA <= 0)
531                         PSG->CountA = 1;
532                 break;
533         case AY_BFINE:
534         case AY_BCOARSE:
535                 PSG->Regs[AY_BCOARSE] &= 0x0F;
536                 old = PSG->PeriodB;
537                 PSG->PeriodB = (PSG->Regs[AY_BFINE] + 256 * PSG->Regs[AY_BCOARSE]) * PSG->UpdateStep;
538
539                 if (PSG->PeriodB == 0)
540                         PSG->PeriodB = PSG->UpdateStep;
541
542                 PSG->CountB += PSG->PeriodB - old;
543
544                 if (PSG->CountB <= 0)
545                         PSG->CountB = 1;
546                 break;
547         case AY_CFINE:
548         case AY_CCOARSE:
549                 PSG->Regs[AY_CCOARSE] &= 0x0F;
550                 old = PSG->PeriodC;
551                 PSG->PeriodC = (PSG->Regs[AY_CFINE] + 256 * PSG->Regs[AY_CCOARSE]) * PSG->UpdateStep;
552
553                 if (PSG->PeriodC == 0)
554                         PSG->PeriodC = PSG->UpdateStep;
555
556                 PSG->CountC += PSG->PeriodC - old;
557
558                 if (PSG->CountC <= 0)
559                         PSG->CountC = 1;
560                 break;
561         case AY_NOISEPER:
562                 PSG->Regs[AY_NOISEPER] &= 0x1F;
563                 old = PSG->PeriodN;
564                 PSG->PeriodN = PSG->Regs[AY_NOISEPER] * PSG->UpdateStep;
565
566                 if (PSG->PeriodN == 0)
567                         PSG->PeriodN = PSG->UpdateStep;
568
569                 PSG->CountN += PSG->PeriodN - old;
570
571                 if (PSG->CountN <= 0)
572                         PSG->CountN = 1;
573                 break;
574 /*      case AY_ENABLE:
575                 if ((PSG->lastEnable == -1) ||
576                     ((PSG->lastEnable & 0x40) != (PSG->Regs[AY_ENABLE] & 0x40)))
577                 {
578                         // write out $FF if port set to input
579                         if (PSG->PortAwrite)
580                                 (*PSG->PortAwrite)(0, (UINT8) ((PSG->Regs[AY_ENABLE] & 0x40) ? PSG->Regs[AY_PORTA] : 0xff));    // [TC: UINT8 cast]
581                 }
582
583                 if ((PSG->lastEnable == -1) ||
584                     ((PSG->lastEnable & 0x80) != (PSG->Regs[AY_ENABLE] & 0x80)))
585                 {
586                         // write out $FF if port set to input
587                         if (PSG->PortBwrite)
588                                 (*PSG->PortBwrite)(0, (UINT8) ((PSG->Regs[AY_ENABLE] & 0x80) ? PSG->Regs[AY_PORTB] : 0xff));    // [TC: UINT8 cast]
589                 }
590
591                 PSG->lastEnable = PSG->Regs[AY_ENABLE];
592                 break;*/
593         case AY_AVOL:
594                 PSG->Regs[AY_AVOL] &= 0x1F;
595                 PSG->EnvelopeA = PSG->Regs[AY_AVOL] & 0x10;
596                 PSG->VolA = (PSG->EnvelopeA ? PSG->VolE :
597                         (PSG->VolTable[PSG->Regs[AY_AVOL] ? PSG->Regs[AY_AVOL] * 2 + 1
598                                 : 0]));
599                 break;
600         case AY_BVOL:
601                 PSG->Regs[AY_BVOL] &= 0x1F;
602                 PSG->EnvelopeB = PSG->Regs[AY_BVOL] & 0x10;
603                 PSG->VolB = (PSG->EnvelopeB ? PSG->VolE :
604                         (PSG->VolTable[PSG->Regs[AY_BVOL] ? PSG->Regs[AY_BVOL] * 2 + 1
605                                 : 0]));
606                 break;
607         case AY_CVOL:
608                 PSG->Regs[AY_CVOL] &= 0x1F;
609                 PSG->EnvelopeC = PSG->Regs[AY_CVOL] & 0x10;
610                 PSG->VolC = (PSG->EnvelopeC ? PSG->VolE
611                         : (PSG->VolTable[PSG->Regs[AY_CVOL] ? PSG->Regs[AY_CVOL] * 2 + 1
612                                 : 0]));
613                 break;
614         case AY_EFINE:
615         case AY_ECOARSE:
616                 old = PSG->PeriodE;
617                 PSG->PeriodE = ((PSG->Regs[AY_EFINE] + 256 * PSG->Regs[AY_ECOARSE])) * PSG->UpdateStep;
618
619                 if (PSG->PeriodE == 0)
620                         PSG->PeriodE = PSG->UpdateStep / 2;
621
622                 PSG->CountE += PSG->PeriodE - old;
623
624                 if (PSG->CountE <= 0)
625                         PSG->CountE = 1;
626                 break;
627         case AY_ESHAPE:
628                 /* envelope shapes:
629                 C AtAlH
630                 0 0 x x  \___
631
632                 0 1 x x  /___
633
634                 1 0 0 0  \\\\
635
636                 1 0 0 1  \___
637
638                 1 0 1 0  \/\/
639                           ___
640                 1 0 1 1  \
641
642                 1 1 0 0  ////
643                           ___
644                 1 1 0 1  /
645
646                 1 1 1 0  /\/\
647
648                 1 1 1 1  /___
649
650                 The envelope counter on the AY-3-8910 has 16 steps. On the YM2149 it
651                 has twice the steps, happening twice as fast. Since the end result is
652                 just a smoother curve, we always use the YM2149 behaviour.
653                 */
654                 PSG->Regs[AY_ESHAPE] &= 0x0F;
655                 PSG->Attack = (PSG->Regs[AY_ESHAPE] & 0x04 ? 0x1F : 0x00);
656
657                 if ((PSG->Regs[AY_ESHAPE] & 0x08) == 0)
658                 {
659                         /* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */
660                         PSG->Hold = 1;
661                         PSG->Alternate = PSG->Attack;
662                 }
663                 else
664                 {
665                         PSG->Hold = PSG->Regs[AY_ESHAPE] & 0x01;
666                         PSG->Alternate = PSG->Regs[AY_ESHAPE] & 0x02;
667                 }
668
669                 PSG->CountE = PSG->PeriodE;
670                 PSG->CountEnv = 0x1F;
671                 PSG->Holding = 0;
672                 PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack];
673
674                 if (PSG->EnvelopeA)
675                         PSG->VolA = PSG->VolE;
676
677                 if (PSG->EnvelopeB)
678                         PSG->VolB = PSG->VolE;
679
680                 if (PSG->EnvelopeC)
681                         PSG->VolC = PSG->VolE;
682                 break;
683 /*      case AY_PORTA:
684                 if (PSG->Regs[AY_ENABLE] & 0x40)
685                 {
686                         if (PSG->PortAwrite)
687                                 (*PSG->PortAwrite)(0, PSG->Regs[AY_PORTA]);
688                         else
689                                 logerror("PC %04x: warning - write %02x to 8910 #%d Port A\n",activecpu_get_pc(),PSG->Regs[AY_PORTA],n);
690                 }
691                 else
692                 {
693                         logerror("warning: write to 8910 #%d Port A set as input - ignored\n",n);
694                 }
695                 break;
696         case AY_PORTB:
697                 if (PSG->Regs[AY_ENABLE] & 0x80)
698                 {
699                         if (PSG->PortBwrite)
700                                 (*PSG->PortBwrite)(0, PSG->Regs[AY_PORTB]);
701                         else
702                                 logerror("PC %04x: warning - write %02x to 8910 #%d Port B\n",activecpu_get_pc(),PSG->Regs[AY_PORTB],n);
703                 }
704                 else
705                 {
706                         logerror("warning: write to 8910 #%d Port B set as input - ignored\n",n);
707                 }
708                 break;*/
709         }
710 }
711
712
713 //#define DEBUG_AY
714 // /length/ is the number of samples we require
715 void AY8910Update(int chip, int16_t ** buffer, int length)      // [TC: Removed static]
716 {
717 #ifdef DEBUG_AY
718 WriteLog("AY8910Update: chip=%d, buffer=%X, length=%d\n", chip, buffer, length);
719 #endif
720         struct AY8910 * PSG = &AYPSG[chip];
721
722         int16_t * buf1 = buffer[0];
723         int16_t * buf2 = buffer[1];
724         int16_t * buf3 = buffer[2];
725
726         /* The 8910 has three outputs, each output is the mix of one of the three
727          * tone generators and of the (single) noise generator. The two are mixed
728          * BEFORE going into the DAC. The formula to mix each channel is:
729          * (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable).
730          * Note that this means that if both tone and noise are disabled, the
731          * output is 1, not 0, and can be modulated changing the volume.
732          *
733          * If the channels are disabled, set their output to 1, and increase the
734          * counter, if necessary, so they will not be inverted during this update.
735          * Setting the output to 1 is necessary because a disabled channel is
736          * locked into the ON state (see above); and it has no effect if the volume
737          * is 0. If the volume is 0, increase the counter, but don't touch the
738          * output.
739          */
740         // N.B.: The bits in AY_ENABLE (0-5) are all active LOW, which means if the
741         //       channel bit is set, it is DISABLED.  5-3 are noise, 2-0 tone.
742         if (PSG->Regs[AY_ENABLE] & 0x01)
743         {
744                 if (PSG->CountA <= length * STEP)
745                         PSG->CountA += length * STEP;
746
747                 PSG->OutputA = 1;
748         }
749         else if (PSG->Regs[AY_AVOL] == 0)
750         {
751                 /* note that I do count += length, NOT count = length + 1. You might
752                  * think it's the same since the volume is 0, but doing the latter
753                  * could cause interferencies when the program is rapidly modulating
754                  * the volume.
755                  */
756                 if (PSG->CountA <= length * STEP)
757                         PSG->CountA += length * STEP;
758         }
759
760         if (PSG->Regs[AY_ENABLE] & 0x02)
761         {
762                 if (PSG->CountB <= length * STEP)
763                         PSG->CountB += length * STEP;
764
765                 PSG->OutputB = 1;
766         }
767         else if (PSG->Regs[AY_BVOL] == 0)
768         {
769                 if (PSG->CountB <= length * STEP)
770                         PSG->CountB += length * STEP;
771         }
772
773         if (PSG->Regs[AY_ENABLE] & 0x04)
774         {
775                 if (PSG->CountC <= length * STEP)
776                         PSG->CountC += length * STEP;
777
778                 PSG->OutputC = 1;
779         }
780         else if (PSG->Regs[AY_CVOL] == 0)
781         {
782                 if (PSG->CountC <= length * STEP)
783                         PSG->CountC += length * STEP;
784         }
785
786         /* for the noise channel we must not touch OutputN - it's also not
787          * necessary since we use outn.                                                        */
788         if ((PSG->Regs[AY_ENABLE] & 0x38) == 0x38)      /* all off */
789                 if (PSG->CountN <= length * STEP)
790                         PSG->CountN += length * STEP;
791
792         int outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);
793
794 #ifdef DEBUG_AY
795 WriteLog("AY8910Update: Stepping into while (length)...\n");
796 #endif
797         /* buffering loop */
798         while (length)
799         {
800                 /* vola, volb and volc keep track of how long each square wave stays
801                  * in the 1 position during the sample period.
802                  */
803                 int vola = 0, volb = 0, volc = 0;
804                 int left = STEP;
805
806 #ifdef DEBUG_AY
807 WriteLog("AY8910Update: Stepping into inner do loop... (length=%d)\n", length);
808 #endif
809                 do
810                 {
811                         int nextevent = (PSG->CountN < left ? PSG->CountN : left);
812 //Note: nextevent is 0 here when first initialized...
813 //so let's try this:
814                         if (nextevent == 0)
815                                 left = 0;
816 #ifdef DEBUG_AY
817 WriteLog("AY8910Update: nextevent=$%X, left=$%X\n", nextevent, left);
818 #endif
819
820                         if (outn & 0x08)
821                         {
822                                 if (PSG->OutputA)
823                                         vola += PSG->CountA;
824
825                                 PSG->CountA -= nextevent;
826                                 /* PeriodA is the half period of the square wave. Here, in each
827                                  * loop I add PeriodA twice, so that at the end of the loop the
828                                  * square wave is in the same status (0 or 1) it was at the
829                                  * start. vola is also incremented by PeriodA, since the wave
830                                  * has been 1 exactly half of the time, regardless of the
831                                  * initial position. If we exit the loop in the middle, OutputA
832                                  * has to be inverted and vola incremented only if the exit
833                                  * status of the square wave is 1.                                                      */
834                                 while (PSG->CountA <= 0)
835                                 {
836                                         PSG->CountA += PSG->PeriodA;
837
838                                         if (PSG->CountA > 0)
839                                         {
840                                                 PSG->OutputA ^= 1;
841
842                                                 if (PSG->OutputA)
843                                                         vola += PSG->PeriodA;
844
845                                                 break;
846                                         }
847
848                                         PSG->CountA += PSG->PeriodA;
849                                         vola += PSG->PeriodA;
850                                 }
851
852                                 if (PSG->OutputA)
853                                         vola -= PSG->CountA;
854                         }
855                         else
856                         {
857                                 PSG->CountA -= nextevent;
858
859                                 while (PSG->CountA <= 0)
860                                 {
861                                         PSG->CountA += PSG->PeriodA;
862
863                                         if (PSG->CountA > 0)
864                                         {
865                                                 PSG->OutputA ^= 1;
866                                                 break;
867                                         }
868
869                                         PSG->CountA += PSG->PeriodA;
870                                 }
871                         }
872
873                         if (outn & 0x10)
874                         {
875                                 if (PSG->OutputB)
876                                         volb += PSG->CountB;
877
878                                 PSG->CountB -= nextevent;
879
880                                 while (PSG->CountB <= 0)
881                                 {
882                                         PSG->CountB += PSG->PeriodB;
883
884                                         if (PSG->CountB > 0)
885                                         {
886                                                 PSG->OutputB ^= 1;
887
888                                                 if (PSG->OutputB)
889                                                         volb += PSG->PeriodB;
890                                                 break;
891                                         }
892
893                                         PSG->CountB += PSG->PeriodB;
894                                         volb += PSG->PeriodB;
895                                 }
896
897                                 if (PSG->OutputB)
898                                         volb -= PSG->CountB;
899                         }
900                         else
901                         {
902                                 PSG->CountB -= nextevent;
903
904                                 while (PSG->CountB <= 0)
905                                 {
906                                         PSG->CountB += PSG->PeriodB;
907
908                                         if (PSG->CountB > 0)
909                                         {
910                                                 PSG->OutputB ^= 1;
911                                                 break;
912                                         }
913
914                                         PSG->CountB += PSG->PeriodB;
915                                 }
916                         }
917
918                         if (outn & 0x20)
919                         {
920                                 if (PSG->OutputC)
921                                         volc += PSG->CountC;
922
923                                 PSG->CountC -= nextevent;
924
925                                 while (PSG->CountC <= 0)
926                                 {
927                                         PSG->CountC += PSG->PeriodC;
928
929                                         if (PSG->CountC > 0)
930                                         {
931                                                 PSG->OutputC ^= 1;
932
933                                                 if (PSG->OutputC)
934                                                         volc += PSG->PeriodC;
935                                                 break;
936                                         }
937
938                                         PSG->CountC += PSG->PeriodC;
939                                         volc += PSG->PeriodC;
940                                 }
941
942                                 if (PSG->OutputC)
943                                         volc -= PSG->CountC;
944                         }
945                         else
946                         {
947                                 PSG->CountC -= nextevent;
948
949                                 while (PSG->CountC <= 0)
950                                 {
951                                         PSG->CountC += PSG->PeriodC;
952
953                                         if (PSG->CountC > 0)
954                                         {
955                                                 PSG->OutputC ^= 1;
956                                                 break;
957                                         }
958
959                                         PSG->CountC += PSG->PeriodC;
960                                 }
961                         }
962
963                         PSG->CountN -= nextevent;
964
965                         if (PSG->CountN <= 0)
966                         {
967                                 /* Is noise output going to change? */
968                                 if ((PSG->RNG + 1) & 0x00002)   // (bit0 XOR bit1) == 1?
969                                 {
970                                         PSG->OutputN = ~PSG->OutputN;
971                                         outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);
972                                 }
973
974                                 /* The Random Number Generator of the 8910 is a 17-bit shift
975                                  * register. The input to the shift register is bit0 XOR bit3
976                                  * (bit0 is the output). This was verified on AY-3-8910 and
977                                  * YM2149 chips.
978                                  *
979                                  * The following is a fast way to compute bit17 = bit0^bit3.
980                                  * Instead of doing all the logic operations, we only check
981                                  * bit0, relying on the fact that after three shifts of the
982                                  * register, what now is bit3 will become bit0, and will
983                                  * invert, if necessary, bit14, which previously was bit17.   */
984                                 if (PSG->RNG & 0x00001)
985                                         PSG->RNG ^= 0x24000; /* This version is called the "Galois configuration". */
986
987                                 PSG->RNG >>= 1;
988                                 PSG->CountN += PSG->PeriodN;
989                         }
990
991                         left -= nextevent;
992                 }
993                 while (left > 0);
994
995 #ifdef DEBUG_AY
996 WriteLog("AY8910Update: About to update envelope...\n");
997 #endif
998                 /* update envelope */
999                 if (PSG->Holding == 0)
1000                 {
1001                         PSG->CountE -= STEP;
1002
1003                         if (PSG->CountE <= 0)
1004                         {
1005 #ifdef DEBUG_AY
1006 WriteLog("AY8910Update: About to enter do loop... (CountEnv = $%X, CountE =$%X, PeriodE = $%X)\n", PSG->CountEnv, PSG->CountE, PSG->PeriodE);
1007 #endif
1008                                 // JLH: Sanity check...
1009                                 if (PSG->PeriodE > 0)
1010                                 {
1011                                         do
1012                                         {
1013                                                 PSG->CountEnv--;
1014                                                 PSG->CountE += PSG->PeriodE;
1015                                         }
1016                                         while (PSG->CountE <= 0);
1017                                 }
1018
1019                                 /* check envelope current position */
1020                                 if (PSG->CountEnv < 0)
1021                                 {
1022                                         if (PSG->Hold)
1023                                         {
1024                                                 if (PSG->Alternate)
1025                                                         PSG->Attack ^= 0x1F;
1026
1027                                                 PSG->Holding = 1;
1028                                                 PSG->CountEnv = 0;
1029                                         }
1030                                         else
1031                                         {
1032                                                 /* if CountEnv has looped an odd number of times
1033                                                  * (usually 1), invert the output.                                         */
1034                                                 if (PSG->Alternate && (PSG->CountEnv & 0x20))
1035                                                         PSG->Attack ^= 0x1F;
1036
1037                                                 PSG->CountEnv &= 0x1F;
1038                                         }
1039                                 }
1040
1041                                 PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack];
1042
1043                                 /* reload volume */
1044                                 if (PSG->EnvelopeA)
1045                                         PSG->VolA = PSG->VolE;
1046
1047                                 if (PSG->EnvelopeB)
1048                                         PSG->VolB = PSG->VolE;
1049
1050                                 if (PSG->EnvelopeC)
1051                                         PSG->VolC = PSG->VolE;
1052                         }
1053                 }
1054
1055 #if 1
1056                 *(buf1++) = (vola * PSG->VolA) / STEP;
1057                 *(buf2++) = (volb * PSG->VolB) / STEP;
1058                 *(buf3++) = (volc * PSG->VolC) / STEP;
1059 #else   // [Tom's code...]
1060                 // Output PCM wave [-32768...32767] instead of MAME's voltage level [0...32767]
1061                 // - This allows for better s/w mixing
1062
1063                 if (PSG->VolA)
1064                 {
1065                         if (vola)
1066                                 *(buf1++) = (vola * PSG->VolA) / STEP;
1067                         else
1068                                 *(buf1++) = -(int)PSG->VolA;
1069                 }
1070                 else
1071                         *(buf1++) = 0;
1072
1073                 if (PSG->VolB)
1074                 {
1075                         if (volb)
1076                                 *(buf2++) = (volb * PSG->VolB) / STEP;
1077                         else
1078                                 *(buf2++) = -(int)PSG->VolB;
1079                 }
1080                 else
1081                         *(buf2++) = 0;
1082
1083                 if (PSG->VolC)
1084                 {
1085                         if (volc)
1086                                 *(buf3++) = (volc * PSG->VolC) / STEP;
1087                         else
1088                                 *(buf3++) = -(int)PSG->VolC;
1089                 }
1090                 else
1091                         *(buf3++) = 0;
1092 #endif
1093                 length--;
1094         }
1095 #ifdef DEBUG_AY
1096 WriteLog("AY8910Update: Done.\n");
1097 #endif
1098 }
1099
1100
1101 static void AY8910_set_clock(int chip, int clock)
1102 {
1103 //      struct AY8910 * PSG = &AYPSG[chip];
1104
1105         /* The step clock for the tone and noise generators is the chip clock
1106          * divided by 8; for the envelope generator of the AY-3-8910, it is half
1107          * that much (clock/16), but the envelope of the YM2149 goes twice as
1108          * fast, therefore again clock/8.
1109          * Here we calculate the number of steps which happen during one sample
1110          * at the given sample rate. No. of events = sample rate / (clock/8).
1111          * STEP is a multiplier used to turn the fraction into a fixed point
1112          * number.
1113          */
1114         AYPSG[chip].UpdateStep = (unsigned int)(((double)STEP * AYPSG[chip].SampleRate * 8 + clock / 2) / clock);       // [TC: unsigned int cast]
1115 }
1116
1117
1118 static void build_mixer_table(int chip)
1119 {
1120         /* calculate the volume->voltage conversion table
1121          * The AY-3-8910 has 16 levels, in a logarithmic scale (3dB per step)
1122          * The YM2149 still has 16 levels for the tone generators, but 32 for
1123          * the envelope generator (1.5dB per step).
1124          */
1125         double out = MAX_OUTPUT;
1126
1127         for(int i=31; i>0; i--)
1128         {
1129                 AYPSG[chip].VolTable[i] = (unsigned int)(out + 0.5);    /* round to nearest */  // [TC: unsigned int cast]
1130                 out /= 1.188502227;     /* = 10 ^ (1.5/20) = 1.5dB */
1131         }
1132
1133         AYPSG[chip].VolTable[0] = 0;
1134 }
1135
1136
1137 void AY8910_reset(int chip)
1138 {
1139         AYPSG[chip].register_latch = 0;
1140         AYPSG[chip].RNG = 1;
1141         AYPSG[chip].OutputA = 0;
1142         AYPSG[chip].OutputB = 0;
1143         AYPSG[chip].OutputC = 0;
1144         AYPSG[chip].OutputN = 0xFF;
1145
1146         for(int i=0; i<=AY_ESHAPE; i++)
1147                 _AYWriteReg(chip, i, 0);        /* AYWriteReg() uses the timer system; we
1148                                                                          * cannot call it at this time because the
1149                                                                          * timer system has not been initialized.                     */
1150 }
1151
1152 // This stuff looks like Tom's code, so let's streamline and un-MSHungarianize this shit:
1153 // [DONE]
1154 // N.B.: Looks like 'clock' is the 65C02 clock rate, and 'sampleRate' is the
1155 //       sample rate set by the audio subsystem.
1156
1157 void AY8910_InitAll(int clock, int sampleRate)
1158 {
1159         for(int chip=0; chip<MAX_8910; chip++)
1160         {
1161                 memset(&AYPSG[chip], 0, sizeof(struct AY8910));
1162                 AYPSG[chip].SampleRate = sampleRate;
1163                 AY8910_set_clock(chip, clock);
1164                 build_mixer_table(chip);
1165         }
1166 }
1167
1168
1169 void AY8910_InitClock(int clock)
1170 {
1171         for(int chip=0; chip<MAX_8910; chip++)
1172                 AY8910_set_clock(chip, clock);
1173 }
1174 #endif
1175