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. :-)
10 // (C) 2018 Underground Software
15 #include <string.h> // for memset()
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
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)
44 // Maximum volume that can be generated by one voice
45 float maxVolume = 8192.0f;
47 // Normalized volumes (zero to one) for AY-3-8910 output, in 16 steps
48 static float normalizedVolume[16];// = {};
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 };
55 // Chip structs (for up to four separate chips)
56 static AY_3_8910 ay[4];
61 for(int chip=0; chip<4; chip++)
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).
70 for(int i=15; i>=0; i--)
72 normalizedVolume[i] = level;
73 level /= 1.4125375446228; // 10.0 ^ (3.0 / 20.0) = 3 dB
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
81 float vol0 = normalizedVolume[0];
82 float vol15 = normalizedVolume[15] - vol0;
84 for(int i=0; i<16; i++)
85 normalizedVolume[i] = (normalizedVolume[i] - vol0) / vol15;
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));
115 void AYReset(int chipNum)
117 memset(&ay[chipNum], 0, sizeof(struct AY_3_8910));
118 ay[chipNum].prng = 1; // Set correct PRNG seed
122 void AYWrite(int chipNum, int reg, int value)
125 static char regname[16][32] = {
143 WriteLog("*** AY(%d) Reg: %s = $%02X\n", chipNum, regname[reg], value);
145 AY_3_8910 * chip = &ay[chipNum];
146 value &= 0xFF; // Ensure passed in value is no larger than 8 bits
151 // The square wave period is the passed in value times 16, so we handle
153 chip->period[0] = (chip->period[0] & 0xF000) | (value << 4);
156 chip->period[0] = ((value & 0x0F) << 12) | (chip->period[0] & 0xFF0);
159 chip->period[1] = (chip->period[1] & 0xF000) | (value << 4);
162 chip->period[1] = ((value & 0x0F) << 12) | (chip->period[1] & 0xFF0);
165 chip->period[2] = (chip->period[2] & 0xF000) | (value << 4);
168 chip->period[2] = ((value & 0x0F) << 12) | (chip->period[2] & 0xFF0);
171 // Like the square wave period, the value is the what's passed * 16.
172 chip->noisePeriod = (value & 0x1F) << 4;
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);
183 chip->volume[0] = value & 0x0F;
184 chip->envEnable[0] = (value & 0x10 ? true : false);
186 if (chip->envEnable[0])
188 chip->envCount[0] = 0;
189 chip->volume[0] = (chip->envAttack ? 0 : 15);
190 chip->envDirection[0] = (chip->envAttack ? 1 : -1);
194 chip->volume[1] = value & 0x0F;
195 chip->envEnable[1] = (value & 0x10 ? true : false);
197 if (chip->envEnable[1])
199 chip->envCount[1] = 0;
200 chip->volume[1] = (chip->envAttack ? 0 : 15);
201 chip->envDirection[1] = (chip->envAttack ? 1 : -1);
205 chip->volume[2] = value & 0x0F;
206 chip->envEnable[2] = (value & 0x10 ? true : false);
208 if (chip->envEnable[2])
210 chip->envCount[2] = 0;
211 chip->volume[2] = (chip->envAttack ? 0 : 15);
212 chip->envDirection[2] = (chip->envAttack ? 1 : -1);
216 // The envelope period is 256 times the passed in value
217 chip->envPeriod = (chip->envPeriod & 0xFF0000) | (value << 8);
220 chip->envPeriod = (value << 16) | (chip->envPeriod & 0xFF00);
223 chip->envAttack = (value & 0x04 ? true : false);
224 chip->envAlternate = (value & 0x02 ? true : false);
225 chip->envHold = (value & 0x01 ? true : false);
227 // If the Continue bit is *not* set, the Alternate bit is forced to the
228 // Attack bit, and Hold is forced on.
231 chip->envAlternate = chip->envAttack;
232 chip->envHold = true;
235 // Reset all voice envelope counts...
236 for(int i=0; i<3; i++)
238 chip->envCount[i] = 0;
239 chip->envDirection[i] = (chip->envAttack ? 1 : -1);
241 // Only reset the volume if the envelope is enabled!
242 if (chip->envEnable[i])
243 chip->volume[i] = (chip->envAttack ? 0 : 15);
251 // Generate one sample and quit
253 bool logAYInternal = false;
254 uint16_t AYGetSample(int chipNum)
256 AY_3_8910 * chip = &ay[chipNum];
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;
264 int fullCycles = (int)exactCycles;
265 overflow += exactCycles - (double)fullCycles;
273 for(int i=0; i<fullCycles; i++)
275 for(int j=0; j<3; j++)
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))
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))
288 chip->state[j] = !chip->state[j];
292 // Envelope generator only runs if the corresponding voice flag is
294 if (chip->envEnable[j])
298 // It's (EP / 16) because there are 16 volume steps in each EP.
299 if (chip->envCount[j] > (chip->envPeriod / 16))
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;
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];
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))
314 // Hold means we set the volume to (Alternate XOR
315 // Attack) and stay there after the Attack EP.
318 chip->volume[j] = (chip->envAttack != chip->envAlternate ? 15: 0);
319 chip->envDirection[j] = 0;
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)
328 chip->envDirection[j] = -chip->envDirection[j];
329 chip->volume[j] += chip->envDirection[j];
332 chip->volume[j] = (chip->envAttack ? 0 : 15);
339 // Noise generator (the PRNG) runs all the time:
342 if (chip->noiseCount > chip->noisePeriod)
344 chip->noiseCount = 0;
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.
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)
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;
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++)
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);
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])
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]);
400 // STUFF TO DELETE...
404 /***************************************************************************
408 Emulation of the AY-3-8910 / YM2149 sound chip.
410 Based on various code snippets by Ville Hallik, Michael Cuddy,
411 Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria.
413 ***************************************************************************/
416 // From mame.txt (http://www.mame.net/readme.html)
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.
433 // JLH: Commented out MAME specific crap
435 #define MAX_OUTPUT 0x7FFF
437 // See AY8910_set_clock() for definition of STEP
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;
455 unsigned int VolTable[32];
458 static struct AY8910 AYPSG[MAX_8910]; /* array of PSG's */
461 #define AY_ACOARSE (1)
463 #define AY_BCOARSE (3)
465 #define AY_CCOARSE (5)
466 #define AY_NOISEPER (6)
467 #define AY_ENABLE (7)
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)
478 void _AYWriteReg(int n, int r, int v)
481 static char regname[16][32] = {
499 WriteLog("*** AY(%d) Reg: %s = $%02X\n", n, regname[r], v);
501 struct AY8910 * PSG = &AYPSG[n];
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. */
520 PSG->Regs[AY_ACOARSE] &= 0x0F;
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;
525 if (PSG->PeriodA == 0)
526 PSG->PeriodA = PSG->UpdateStep;
528 PSG->CountA += PSG->PeriodA - old;
530 if (PSG->CountA <= 0)
535 PSG->Regs[AY_BCOARSE] &= 0x0F;
537 PSG->PeriodB = (PSG->Regs[AY_BFINE] + 256 * PSG->Regs[AY_BCOARSE]) * PSG->UpdateStep;
539 if (PSG->PeriodB == 0)
540 PSG->PeriodB = PSG->UpdateStep;
542 PSG->CountB += PSG->PeriodB - old;
544 if (PSG->CountB <= 0)
549 PSG->Regs[AY_CCOARSE] &= 0x0F;
551 PSG->PeriodC = (PSG->Regs[AY_CFINE] + 256 * PSG->Regs[AY_CCOARSE]) * PSG->UpdateStep;
553 if (PSG->PeriodC == 0)
554 PSG->PeriodC = PSG->UpdateStep;
556 PSG->CountC += PSG->PeriodC - old;
558 if (PSG->CountC <= 0)
562 PSG->Regs[AY_NOISEPER] &= 0x1F;
564 PSG->PeriodN = PSG->Regs[AY_NOISEPER] * PSG->UpdateStep;
566 if (PSG->PeriodN == 0)
567 PSG->PeriodN = PSG->UpdateStep;
569 PSG->CountN += PSG->PeriodN - old;
571 if (PSG->CountN <= 0)
575 if ((PSG->lastEnable == -1) ||
576 ((PSG->lastEnable & 0x40) != (PSG->Regs[AY_ENABLE] & 0x40)))
578 // write out $FF if port set to input
580 (*PSG->PortAwrite)(0, (UINT8) ((PSG->Regs[AY_ENABLE] & 0x40) ? PSG->Regs[AY_PORTA] : 0xff)); // [TC: UINT8 cast]
583 if ((PSG->lastEnable == -1) ||
584 ((PSG->lastEnable & 0x80) != (PSG->Regs[AY_ENABLE] & 0x80)))
586 // write out $FF if port set to input
588 (*PSG->PortBwrite)(0, (UINT8) ((PSG->Regs[AY_ENABLE] & 0x80) ? PSG->Regs[AY_PORTB] : 0xff)); // [TC: UINT8 cast]
591 PSG->lastEnable = PSG->Regs[AY_ENABLE];
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
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
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
617 PSG->PeriodE = ((PSG->Regs[AY_EFINE] + 256 * PSG->Regs[AY_ECOARSE])) * PSG->UpdateStep;
619 if (PSG->PeriodE == 0)
620 PSG->PeriodE = PSG->UpdateStep / 2;
622 PSG->CountE += PSG->PeriodE - old;
624 if (PSG->CountE <= 0)
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.
654 PSG->Regs[AY_ESHAPE] &= 0x0F;
655 PSG->Attack = (PSG->Regs[AY_ESHAPE] & 0x04 ? 0x1F : 0x00);
657 if ((PSG->Regs[AY_ESHAPE] & 0x08) == 0)
659 /* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */
661 PSG->Alternate = PSG->Attack;
665 PSG->Hold = PSG->Regs[AY_ESHAPE] & 0x01;
666 PSG->Alternate = PSG->Regs[AY_ESHAPE] & 0x02;
669 PSG->CountE = PSG->PeriodE;
670 PSG->CountEnv = 0x1F;
672 PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack];
675 PSG->VolA = PSG->VolE;
678 PSG->VolB = PSG->VolE;
681 PSG->VolC = PSG->VolE;
684 if (PSG->Regs[AY_ENABLE] & 0x40)
687 (*PSG->PortAwrite)(0, PSG->Regs[AY_PORTA]);
689 logerror("PC %04x: warning - write %02x to 8910 #%d Port A\n",activecpu_get_pc(),PSG->Regs[AY_PORTA],n);
693 logerror("warning: write to 8910 #%d Port A set as input - ignored\n",n);
697 if (PSG->Regs[AY_ENABLE] & 0x80)
700 (*PSG->PortBwrite)(0, PSG->Regs[AY_PORTB]);
702 logerror("PC %04x: warning - write %02x to 8910 #%d Port B\n",activecpu_get_pc(),PSG->Regs[AY_PORTB],n);
706 logerror("warning: write to 8910 #%d Port B set as input - ignored\n",n);
714 // /length/ is the number of samples we require
715 void AY8910Update(int chip, int16_t ** buffer, int length) // [TC: Removed static]
718 WriteLog("AY8910Update: chip=%d, buffer=%X, length=%d\n", chip, buffer, length);
720 struct AY8910 * PSG = &AYPSG[chip];
722 int16_t * buf1 = buffer[0];
723 int16_t * buf2 = buffer[1];
724 int16_t * buf3 = buffer[2];
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.
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
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)
744 if (PSG->CountA <= length * STEP)
745 PSG->CountA += length * STEP;
749 else if (PSG->Regs[AY_AVOL] == 0)
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
756 if (PSG->CountA <= length * STEP)
757 PSG->CountA += length * STEP;
760 if (PSG->Regs[AY_ENABLE] & 0x02)
762 if (PSG->CountB <= length * STEP)
763 PSG->CountB += length * STEP;
767 else if (PSG->Regs[AY_BVOL] == 0)
769 if (PSG->CountB <= length * STEP)
770 PSG->CountB += length * STEP;
773 if (PSG->Regs[AY_ENABLE] & 0x04)
775 if (PSG->CountC <= length * STEP)
776 PSG->CountC += length * STEP;
780 else if (PSG->Regs[AY_CVOL] == 0)
782 if (PSG->CountC <= length * STEP)
783 PSG->CountC += length * STEP;
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;
792 int outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);
795 WriteLog("AY8910Update: Stepping into while (length)...\n");
800 /* vola, volb and volc keep track of how long each square wave stays
801 * in the 1 position during the sample period.
803 int vola = 0, volb = 0, volc = 0;
807 WriteLog("AY8910Update: Stepping into inner do loop... (length=%d)\n", length);
811 int nextevent = (PSG->CountN < left ? PSG->CountN : left);
812 //Note: nextevent is 0 here when first initialized...
817 WriteLog("AY8910Update: nextevent=$%X, left=$%X\n", nextevent, left);
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)
836 PSG->CountA += PSG->PeriodA;
843 vola += PSG->PeriodA;
848 PSG->CountA += PSG->PeriodA;
849 vola += PSG->PeriodA;
857 PSG->CountA -= nextevent;
859 while (PSG->CountA <= 0)
861 PSG->CountA += PSG->PeriodA;
869 PSG->CountA += PSG->PeriodA;
878 PSG->CountB -= nextevent;
880 while (PSG->CountB <= 0)
882 PSG->CountB += PSG->PeriodB;
889 volb += PSG->PeriodB;
893 PSG->CountB += PSG->PeriodB;
894 volb += PSG->PeriodB;
902 PSG->CountB -= nextevent;
904 while (PSG->CountB <= 0)
906 PSG->CountB += PSG->PeriodB;
914 PSG->CountB += PSG->PeriodB;
923 PSG->CountC -= nextevent;
925 while (PSG->CountC <= 0)
927 PSG->CountC += PSG->PeriodC;
934 volc += PSG->PeriodC;
938 PSG->CountC += PSG->PeriodC;
939 volc += PSG->PeriodC;
947 PSG->CountC -= nextevent;
949 while (PSG->CountC <= 0)
951 PSG->CountC += PSG->PeriodC;
959 PSG->CountC += PSG->PeriodC;
963 PSG->CountN -= nextevent;
965 if (PSG->CountN <= 0)
967 /* Is noise output going to change? */
968 if ((PSG->RNG + 1) & 0x00002) // (bit0 XOR bit1) == 1?
970 PSG->OutputN = ~PSG->OutputN;
971 outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);
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
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". */
988 PSG->CountN += PSG->PeriodN;
996 WriteLog("AY8910Update: About to update envelope...\n");
998 /* update envelope */
999 if (PSG->Holding == 0)
1001 PSG->CountE -= STEP;
1003 if (PSG->CountE <= 0)
1006 WriteLog("AY8910Update: About to enter do loop... (CountEnv = $%X, CountE =$%X, PeriodE = $%X)\n", PSG->CountEnv, PSG->CountE, PSG->PeriodE);
1008 // JLH: Sanity check...
1009 if (PSG->PeriodE > 0)
1014 PSG->CountE += PSG->PeriodE;
1016 while (PSG->CountE <= 0);
1019 /* check envelope current position */
1020 if (PSG->CountEnv < 0)
1025 PSG->Attack ^= 0x1F;
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;
1037 PSG->CountEnv &= 0x1F;
1041 PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack];
1045 PSG->VolA = PSG->VolE;
1048 PSG->VolB = PSG->VolE;
1051 PSG->VolC = PSG->VolE;
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
1066 *(buf1++) = (vola * PSG->VolA) / STEP;
1068 *(buf1++) = -(int)PSG->VolA;
1076 *(buf2++) = (volb * PSG->VolB) / STEP;
1078 *(buf2++) = -(int)PSG->VolB;
1086 *(buf3++) = (volc * PSG->VolC) / STEP;
1088 *(buf3++) = -(int)PSG->VolC;
1096 WriteLog("AY8910Update: Done.\n");
1101 static void AY8910_set_clock(int chip, int clock)
1103 // struct AY8910 * PSG = &AYPSG[chip];
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
1114 AYPSG[chip].UpdateStep = (unsigned int)(((double)STEP * AYPSG[chip].SampleRate * 8 + clock / 2) / clock); // [TC: unsigned int cast]
1118 static void build_mixer_table(int chip)
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).
1125 double out = MAX_OUTPUT;
1127 for(int i=31; i>0; i--)
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 */
1133 AYPSG[chip].VolTable[0] = 0;
1137 void AY8910_reset(int chip)
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;
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. */
1152 // This stuff looks like Tom's code, so let's streamline and un-MSHungarianize this shit:
1154 // N.B.: Looks like 'clock' is the 65C02 clock rate, and 'sampleRate' is the
1155 // sample rate set by the audio subsystem.
1157 void AY8910_InitAll(int clock, int sampleRate)
1159 for(int chip=0; chip<MAX_8910; chip++)
1161 memset(&AYPSG[chip], 0, sizeof(struct AY8910));
1162 AYPSG[chip].SampleRate = sampleRate;
1163 AY8910_set_clock(chip, clock);
1164 build_mixer_table(chip);
1169 void AY8910_InitClock(int clock)
1171 for(int chip=0; chip<MAX_8910; chip++)
1172 AY8910_set_clock(chip, clock);