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. :-)
11 // (C) 2018 Underground Software
16 #include <string.h> // for memset()
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
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)
45 // Maximum volume that can be generated by one voice
46 float maxVolume = 8192.0f;
48 // Normalized volumes (zero to one) for AY-3-8910 output, in 16 steps
49 static float normalizedVolume[16];// = {};
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 };
56 // Chip structs (for up to four separate chips)
57 static AY_3_8910 ay[4];
62 for(int chip=0; chip<4; chip++)
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).
71 for(int i=15; i>=0; i--)
73 normalizedVolume[i] = level;
74 level /= 1.4125375446228; // 10.0 ^ (3.0 / 20.0) = 3 dB
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
82 float vol0 = normalizedVolume[0];
83 float vol15 = normalizedVolume[15] - vol0;
85 for(int i=0; i<16; i++)
86 normalizedVolume[i] = (normalizedVolume[i] - vol0) / vol15;
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));
116 void AYReset(int chipNum)
118 memset(&ay[chipNum], 0, sizeof(struct AY_3_8910));
119 ay[chipNum].prng = 1; // Set correct PRNG seed
123 void AYWrite(int chipNum, int reg, int value)
126 static char regname[16][32] = {
144 WriteLog("*** AY(%d) Reg: %s = $%02X\n", chipNum, regname[reg], value);
146 AY_3_8910 * chip = &ay[chipNum];
147 value &= 0xFF; // Ensure passed in value is no larger than 8 bits
152 // The square wave period is the passed in value times 16, so we handle
154 chip->period[0] = (chip->period[0] & 0xF000) | (value << 4);
157 chip->period[0] = ((value & 0x0F) << 12) | (chip->period[0] & 0xFF0);
160 chip->period[1] = (chip->period[1] & 0xF000) | (value << 4);
163 chip->period[1] = ((value & 0x0F) << 12) | (chip->period[1] & 0xFF0);
166 chip->period[2] = (chip->period[2] & 0xF000) | (value << 4);
169 chip->period[2] = ((value & 0x0F) << 12) | (chip->period[2] & 0xFF0);
172 // Like the square wave period, the value is the what's passed * 16.
173 chip->noisePeriod = (value & 0x1F) << 4;
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);
184 chip->volume[0] = value & 0x0F;
185 chip->envEnable[0] = (value & 0x10 ? true : false);
187 if (chip->envEnable[0])
189 chip->envCount[0] = 0;
190 chip->volume[0] = (chip->envAttack ? 0 : 15);
191 chip->envDirection[0] = (chip->envAttack ? 1 : -1);
195 chip->volume[1] = value & 0x0F;
196 chip->envEnable[1] = (value & 0x10 ? true : false);
198 if (chip->envEnable[1])
200 chip->envCount[1] = 0;
201 chip->volume[1] = (chip->envAttack ? 0 : 15);
202 chip->envDirection[1] = (chip->envAttack ? 1 : -1);
206 chip->volume[2] = value & 0x0F;
207 chip->envEnable[2] = (value & 0x10 ? true : false);
209 if (chip->envEnable[2])
211 chip->envCount[2] = 0;
212 chip->volume[2] = (chip->envAttack ? 0 : 15);
213 chip->envDirection[2] = (chip->envAttack ? 1 : -1);
217 // The envelope period is 256 times the passed in value
218 chip->envPeriod = (chip->envPeriod & 0xFF0000) | (value << 8);
221 chip->envPeriod = (value << 16) | (chip->envPeriod & 0xFF00);
224 chip->envAttack = (value & 0x04 ? true : false);
225 chip->envAlternate = (value & 0x02 ? true : false);
226 chip->envHold = (value & 0x01 ? true : false);
228 // If the Continue bit is *not* set, the Alternate bit is forced to the
229 // Attack bit, and Hold is forced on.
232 chip->envAlternate = chip->envAttack;
233 chip->envHold = true;
236 // Reset all voice envelope counts...
237 for(int i=0; i<3; i++)
239 chip->envCount[i] = 0;
240 chip->envDirection[i] = (chip->envAttack ? 1 : -1);
242 // Only reset the volume if the envelope is enabled!
243 if (chip->envEnable[i])
244 chip->volume[i] = (chip->envAttack ? 0 : 15);
252 // Generate one sample and quit
254 bool logAYInternal = false;
255 uint16_t AYGetSample(int chipNum)
257 AY_3_8910 * chip = &ay[chipNum];
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;
265 int fullCycles = (int)exactCycles;
266 overflow += exactCycles - (double)fullCycles;
274 for(int i=0; i<fullCycles; i++)
276 for(int j=0; j<3; j++)
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))
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))
289 chip->state[j] = !chip->state[j];
293 // Envelope generator only runs if the corresponding voice flag is
295 if (chip->envEnable[j])
299 // It's (EP / 16) because there are 16 volume steps in each EP.
300 if (chip->envCount[j] > (chip->envPeriod / 16))
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;
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];
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))
315 // Hold means we set the volume to (Alternate XOR
316 // Attack) and stay there after the Attack EP.
319 chip->volume[j] = (chip->envAttack != chip->envAlternate ? 15: 0);
320 chip->envDirection[j] = 0;
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)
329 chip->envDirection[j] = -chip->envDirection[j];
330 chip->volume[j] += chip->envDirection[j];
333 chip->volume[j] = (chip->envAttack ? 0 : 15);
340 // Noise generator (the PRNG) runs all the time:
343 if (chip->noiseCount > chip->noisePeriod)
345 chip->noiseCount = 0;
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.
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)
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;
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++)
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);
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])
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]);
401 // STUFF TO DELETE...
405 /***************************************************************************
409 Emulation of the AY-3-8910 / YM2149 sound chip.
411 Based on various code snippets by Ville Hallik, Michael Cuddy,
412 Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria.
414 ***************************************************************************/
417 // From mame.txt (http://www.mame.net/readme.html)
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.
434 // JLH: Commented out MAME specific crap
436 #define MAX_OUTPUT 0x7FFF
438 // See AY8910_set_clock() for definition of STEP
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;
456 unsigned int VolTable[32];
459 static struct AY8910 AYPSG[MAX_8910]; /* array of PSG's */
462 #define AY_ACOARSE (1)
464 #define AY_BCOARSE (3)
466 #define AY_CCOARSE (5)
467 #define AY_NOISEPER (6)
468 #define AY_ENABLE (7)
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)
479 void _AYWriteReg(int n, int r, int v)
482 static char regname[16][32] = {
500 WriteLog("*** AY(%d) Reg: %s = $%02X\n", n, regname[r], v);
502 struct AY8910 * PSG = &AYPSG[n];
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. */
521 PSG->Regs[AY_ACOARSE] &= 0x0F;
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;
526 if (PSG->PeriodA == 0)
527 PSG->PeriodA = PSG->UpdateStep;
529 PSG->CountA += PSG->PeriodA - old;
531 if (PSG->CountA <= 0)
536 PSG->Regs[AY_BCOARSE] &= 0x0F;
538 PSG->PeriodB = (PSG->Regs[AY_BFINE] + 256 * PSG->Regs[AY_BCOARSE]) * PSG->UpdateStep;
540 if (PSG->PeriodB == 0)
541 PSG->PeriodB = PSG->UpdateStep;
543 PSG->CountB += PSG->PeriodB - old;
545 if (PSG->CountB <= 0)
550 PSG->Regs[AY_CCOARSE] &= 0x0F;
552 PSG->PeriodC = (PSG->Regs[AY_CFINE] + 256 * PSG->Regs[AY_CCOARSE]) * PSG->UpdateStep;
554 if (PSG->PeriodC == 0)
555 PSG->PeriodC = PSG->UpdateStep;
557 PSG->CountC += PSG->PeriodC - old;
559 if (PSG->CountC <= 0)
563 PSG->Regs[AY_NOISEPER] &= 0x1F;
565 PSG->PeriodN = PSG->Regs[AY_NOISEPER] * PSG->UpdateStep;
567 if (PSG->PeriodN == 0)
568 PSG->PeriodN = PSG->UpdateStep;
570 PSG->CountN += PSG->PeriodN - old;
572 if (PSG->CountN <= 0)
576 if ((PSG->lastEnable == -1) ||
577 ((PSG->lastEnable & 0x40) != (PSG->Regs[AY_ENABLE] & 0x40)))
579 // write out $FF if port set to input
581 (*PSG->PortAwrite)(0, (UINT8) ((PSG->Regs[AY_ENABLE] & 0x40) ? PSG->Regs[AY_PORTA] : 0xff)); // [TC: UINT8 cast]
584 if ((PSG->lastEnable == -1) ||
585 ((PSG->lastEnable & 0x80) != (PSG->Regs[AY_ENABLE] & 0x80)))
587 // write out $FF if port set to input
589 (*PSG->PortBwrite)(0, (UINT8) ((PSG->Regs[AY_ENABLE] & 0x80) ? PSG->Regs[AY_PORTB] : 0xff)); // [TC: UINT8 cast]
592 PSG->lastEnable = PSG->Regs[AY_ENABLE];
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
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
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
618 PSG->PeriodE = ((PSG->Regs[AY_EFINE] + 256 * PSG->Regs[AY_ECOARSE])) * PSG->UpdateStep;
620 if (PSG->PeriodE == 0)
621 PSG->PeriodE = PSG->UpdateStep / 2;
623 PSG->CountE += PSG->PeriodE - old;
625 if (PSG->CountE <= 0)
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.
655 PSG->Regs[AY_ESHAPE] &= 0x0F;
656 PSG->Attack = (PSG->Regs[AY_ESHAPE] & 0x04 ? 0x1F : 0x00);
658 if ((PSG->Regs[AY_ESHAPE] & 0x08) == 0)
660 /* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */
662 PSG->Alternate = PSG->Attack;
666 PSG->Hold = PSG->Regs[AY_ESHAPE] & 0x01;
667 PSG->Alternate = PSG->Regs[AY_ESHAPE] & 0x02;
670 PSG->CountE = PSG->PeriodE;
671 PSG->CountEnv = 0x1F;
673 PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack];
676 PSG->VolA = PSG->VolE;
679 PSG->VolB = PSG->VolE;
682 PSG->VolC = PSG->VolE;
685 if (PSG->Regs[AY_ENABLE] & 0x40)
688 (*PSG->PortAwrite)(0, PSG->Regs[AY_PORTA]);
690 logerror("PC %04x: warning - write %02x to 8910 #%d Port A\n",activecpu_get_pc(),PSG->Regs[AY_PORTA],n);
694 logerror("warning: write to 8910 #%d Port A set as input - ignored\n",n);
698 if (PSG->Regs[AY_ENABLE] & 0x80)
701 (*PSG->PortBwrite)(0, PSG->Regs[AY_PORTB]);
703 logerror("PC %04x: warning - write %02x to 8910 #%d Port B\n",activecpu_get_pc(),PSG->Regs[AY_PORTB],n);
707 logerror("warning: write to 8910 #%d Port B set as input - ignored\n",n);
715 // /length/ is the number of samples we require
716 void AY8910Update(int chip, int16_t ** buffer, int length) // [TC: Removed static]
719 WriteLog("AY8910Update: chip=%d, buffer=%X, length=%d\n", chip, buffer, length);
721 struct AY8910 * PSG = &AYPSG[chip];
723 int16_t * buf1 = buffer[0];
724 int16_t * buf2 = buffer[1];
725 int16_t * buf3 = buffer[2];
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.
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
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)
745 if (PSG->CountA <= length * STEP)
746 PSG->CountA += length * STEP;
750 else if (PSG->Regs[AY_AVOL] == 0)
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
757 if (PSG->CountA <= length * STEP)
758 PSG->CountA += length * STEP;
761 if (PSG->Regs[AY_ENABLE] & 0x02)
763 if (PSG->CountB <= length * STEP)
764 PSG->CountB += length * STEP;
768 else if (PSG->Regs[AY_BVOL] == 0)
770 if (PSG->CountB <= length * STEP)
771 PSG->CountB += length * STEP;
774 if (PSG->Regs[AY_ENABLE] & 0x04)
776 if (PSG->CountC <= length * STEP)
777 PSG->CountC += length * STEP;
781 else if (PSG->Regs[AY_CVOL] == 0)
783 if (PSG->CountC <= length * STEP)
784 PSG->CountC += length * STEP;
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;
793 int outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);
796 WriteLog("AY8910Update: Stepping into while (length)...\n");
801 /* vola, volb and volc keep track of how long each square wave stays
802 * in the 1 position during the sample period.
804 int vola = 0, volb = 0, volc = 0;
808 WriteLog("AY8910Update: Stepping into inner do loop... (length=%d)\n", length);
812 int nextevent = (PSG->CountN < left ? PSG->CountN : left);
813 //Note: nextevent is 0 here when first initialized...
818 WriteLog("AY8910Update: nextevent=$%X, left=$%X\n", nextevent, left);
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)
837 PSG->CountA += PSG->PeriodA;
844 vola += PSG->PeriodA;
849 PSG->CountA += PSG->PeriodA;
850 vola += PSG->PeriodA;
858 PSG->CountA -= nextevent;
860 while (PSG->CountA <= 0)
862 PSG->CountA += PSG->PeriodA;
870 PSG->CountA += PSG->PeriodA;
879 PSG->CountB -= nextevent;
881 while (PSG->CountB <= 0)
883 PSG->CountB += PSG->PeriodB;
890 volb += PSG->PeriodB;
894 PSG->CountB += PSG->PeriodB;
895 volb += PSG->PeriodB;
903 PSG->CountB -= nextevent;
905 while (PSG->CountB <= 0)
907 PSG->CountB += PSG->PeriodB;
915 PSG->CountB += PSG->PeriodB;
924 PSG->CountC -= nextevent;
926 while (PSG->CountC <= 0)
928 PSG->CountC += PSG->PeriodC;
935 volc += PSG->PeriodC;
939 PSG->CountC += PSG->PeriodC;
940 volc += PSG->PeriodC;
948 PSG->CountC -= nextevent;
950 while (PSG->CountC <= 0)
952 PSG->CountC += PSG->PeriodC;
960 PSG->CountC += PSG->PeriodC;
964 PSG->CountN -= nextevent;
966 if (PSG->CountN <= 0)
968 /* Is noise output going to change? */
969 if ((PSG->RNG + 1) & 0x00002) // (bit0 XOR bit1) == 1?
971 PSG->OutputN = ~PSG->OutputN;
972 outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);
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
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". */
989 PSG->CountN += PSG->PeriodN;
997 WriteLog("AY8910Update: About to update envelope...\n");
999 /* update envelope */
1000 if (PSG->Holding == 0)
1002 PSG->CountE -= STEP;
1004 if (PSG->CountE <= 0)
1007 WriteLog("AY8910Update: About to enter do loop... (CountEnv = $%X, CountE =$%X, PeriodE = $%X)\n", PSG->CountEnv, PSG->CountE, PSG->PeriodE);
1009 // JLH: Sanity check...
1010 if (PSG->PeriodE > 0)
1015 PSG->CountE += PSG->PeriodE;
1017 while (PSG->CountE <= 0);
1020 /* check envelope current position */
1021 if (PSG->CountEnv < 0)
1026 PSG->Attack ^= 0x1F;
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;
1038 PSG->CountEnv &= 0x1F;
1042 PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack];
1046 PSG->VolA = PSG->VolE;
1049 PSG->VolB = PSG->VolE;
1052 PSG->VolC = PSG->VolE;
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
1067 *(buf1++) = (vola * PSG->VolA) / STEP;
1069 *(buf1++) = -(int)PSG->VolA;
1077 *(buf2++) = (volb * PSG->VolB) / STEP;
1079 *(buf2++) = -(int)PSG->VolB;
1087 *(buf3++) = (volc * PSG->VolC) / STEP;
1089 *(buf3++) = -(int)PSG->VolC;
1097 WriteLog("AY8910Update: Done.\n");
1102 static void AY8910_set_clock(int chip, int clock)
1104 // struct AY8910 * PSG = &AYPSG[chip];
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
1115 AYPSG[chip].UpdateStep = (unsigned int)(((double)STEP * AYPSG[chip].SampleRate * 8 + clock / 2) / clock); // [TC: unsigned int cast]
1119 static void build_mixer_table(int chip)
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).
1126 double out = MAX_OUTPUT;
1128 for(int i=31; i>0; i--)
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 */
1134 AYPSG[chip].VolTable[0] = 0;
1138 void AY8910_reset(int chip)
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;
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. */
1153 // This stuff looks like Tom's code, so let's streamline and un-MSHungarianize this shit:
1155 // N.B.: Looks like 'clock' is the 65C02 clock rate, and 'sampleRate' is the
1156 // sample rate set by the audio subsystem.
1158 void AY8910_InitAll(int clock, int sampleRate)
1160 for(int chip=0; chip<MAX_8910; chip++)
1162 memset(&AYPSG[chip], 0, sizeof(struct AY8910));
1163 AYPSG[chip].SampleRate = sampleRate;
1164 AY8910_set_clock(chip, clock);
1165 build_mixer_table(chip);
1170 void AY8910_InitClock(int clock)
1172 for(int chip=0; chip<MAX_8910; chip++)
1173 AY8910_set_clock(chip, clock);