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