From 354cacc1c79e04373a3dfcd61c2f69db92632e34 Mon Sep 17 00:00:00 2001 From: Couriersud Date: Sun, 5 Jan 2014 16:18:26 +0000 Subject: [PATCH] Fixed noise period on AY8910. [Dr. Venom, Couriersud] --- src/emu/sound/ay8910.c | 49 ++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/emu/sound/ay8910.c b/src/emu/sound/ay8910.c index 707533c5f17..d8407ccb2cc 100644 --- a/src/emu/sound/ay8910.c +++ b/src/emu/sound/ay8910.c @@ -9,6 +9,13 @@ Mostly rewritten by couriersud in 2008 + Public documentation: + + - http://privatfrickler.de/blick-auf-den-chip-soundchip-general-instruments-ay-3-8910/ + Die pictures of the AY8910 + + - US Patent 4933980 + Games using ADSR: gyruss A list with more games using ADSR can be found here: @@ -144,6 +151,7 @@ has twice the steps, happening twice as fast. #define TONE_VOLUME(_psg, _chan) ( (_psg)->regs[AY_AVOL + (_chan)] & 0x0f) #define TONE_ENVELOPE(_psg, _chan) (((_psg)->regs[AY_AVOL + (_chan)] >> 4) & (((_psg)->device->type() == AY8914) ? 3 : 1)) #define ENVELOPE_PERIOD(_psg) (((_psg)->regs[AY_EFINE] | ((_psg)->regs[AY_ECOARSE]<<8))) +#define NOISE_OUTPUT(_psg) ((_psg)->rng & 1) /************************************* * @@ -171,7 +179,7 @@ struct ay8910_context INT32 last_enable; INT32 count[NUM_CHANNELS]; UINT8 output[NUM_CHANNELS]; - UINT8 output_noise; + UINT8 prescale_noise; INT32 count_noise; INT32 count_env; INT8 env_step; @@ -485,7 +493,6 @@ static void ay8910_write_reg(ay8910_context *psg, int r, int v) /* write out 0xff if port set to input */ psg->portBwrite(0, (psg->regs[AY_ENABLE] & 0x80) ? psg->regs[AY_PORTB] : 0xff); } - psg->last_enable = psg->regs[AY_ENABLE]; break; case AY_ESHAPE: @@ -577,37 +584,33 @@ static STREAM_UPDATE( ay8910_update ) if (psg->count[chan] >= TONE_PERIOD(psg, chan)) { psg->output[chan] ^= 1; - psg->count[chan] = 0;; + psg->count[chan] = 0; } } psg->count_noise++; if (psg->count_noise >= NOISE_PERIOD(psg)) { - /* Is noise output going to change? */ - if ((psg->rng + 1) & 2) /* (bit0^bit1)? */ - { - psg->output_noise ^= 1; - } + /* toggle the prescaler output. Noise is no different to + * channels. + */ + psg->count_noise = 0; + psg->prescale_noise ^= 1; - /* The Random Number Generator of the 8910 is a 17-bit shift */ - /* register. The input to the shift register is bit0 XOR bit3 */ - /* (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. */ + if ( psg->prescale_noise) + { + /* The Random Number Generator of the 8910 is a 17-bit shift */ + /* register. The input to the shift register is bit0 XOR bit3 */ + /* (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. */ - /* The following is a fast way to compute bit17 = bit0^bit3. */ - /* Instead of doing all the logic operations, we only check */ - /* bit0, relying on the fact that after three shifts of the */ - /* register, what now is bit3 will become bit0, and will */ - /* invert, if necessary, bit14, which previously was bit17. */ - if (psg->rng & 1) - psg->rng ^= 0x24000; /* This version is called the "Galois configuration". */ - psg->rng >>= 1; - psg->count_noise = 0; + psg->rng ^= (((psg->rng & 1) ^ ((psg->rng >> 3) & 1)) << 17); + psg->rng >>= 1; + } } for (chan = 0; chan < NUM_CHANNELS; chan++) { - psg->vol_enabled[chan] = (psg->output[chan] | TONE_ENABLEQ(psg, chan)) & (psg->output_noise | NOISE_ENABLEQ(psg, chan)); + psg->vol_enabled[chan] = (psg->output[chan] | TONE_ENABLEQ(psg, chan)) & (NOISE_OUTPUT(psg) | NOISE_ENABLEQ(psg, chan)); } /* update envelope */ @@ -712,7 +715,7 @@ static void ay8910_statesave(ay8910_context *psg, device_t *device) device->save_item(NAME(psg->env_volume)); device->save_item(NAME(psg->output)); - device->save_item(NAME(psg->output_noise)); + device->save_item(NAME(psg->prescale_noise)); device->save_item(NAME(psg->env_step)); device->save_item(NAME(psg->hold)); @@ -804,7 +807,7 @@ void ay8910_reset_ym(void *chip) psg->count[2] = 0; psg->count_noise = 0; psg->count_env = 0; - psg->output_noise = 0x01; + psg->prescale_noise = 0; psg->last_enable = -1; /* force a write */ for (i = 0;i < AY_PORTA;i++) ay8910_write_reg(psg,i,0);