void ay::ayWrite(unsigned char reg, unsigned char val) { regs[reg & 0xf] = val; switch(reg) { case AY_CHNL_A_COARSE: case AY_CHNL_A_FINE: tone_period_init0 = TONE_PERIOD(0); break; case AY_CHNL_B_COARSE: case AY_CHNL_B_FINE: tone_period_init1 = TONE_PERIOD(1); break; case AY_CHNL_C_COARSE: case AY_CHNL_C_FINE: tone_period_init2 = TONE_PERIOD(2); break; case AY_NOISE_PERIOD: noise_period_init = NOISE_PERIOD * 2; break; case AY_MIXER: break; case AY_CHNL_A_VOL: case AY_CHNL_B_VOL: case AY_CHNL_C_VOL: break; case AY_ENV_SHAPE: setEnvelope(); break; case AY_ENV_FINE: case AY_ENV_COARSE: env_period_init = ENVELOPE_PERIOD; break; default: break; } }
static void ay8910_update(void *param,stream_sample_t **inputs, stream_sample_t **buffer,int length) { ay8910_context *psg = param; stream_sample_t *buf[NUM_CHANNELS]; int chan; buf[0] = buffer[0]; buf[1] = NULL; buf[2] = NULL; if (psg->streams == NUM_CHANNELS) { buf[1] = buffer[1]; buf[2] = buffer[2]; } /* hack to prevent us from hanging when starting filtered outputs */ if (!psg->ready) { for (chan = 0; chan < NUM_CHANNELS; chan++) if (buf[chan] != NULL) memset(buf[chan], 0, length * sizeof(*buf[chan])); } /* The 8910 has three outputs, each output is the mix of one of the three */ /* tone generators and of the (single) noise generator. The two are mixed */ /* BEFORE going into the DAC. The formula to mix each channel is: */ /* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */ /* Note that this means that if both tone and noise are disabled, the output */ /* is 1, not 0, and can be modulated changing the volume. */ /* buffering loop */ while (length) { for (chan = 0; chan < NUM_CHANNELS; chan++) { psg->count[chan]++; if (psg->count[chan] >= TONE_PERIOD(psg, chan)) { psg->output[chan] ^= 1; 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; } /* 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; } 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)); } /* update envelope */ if (psg->holding == 0) { psg->count_env++; if (psg->count_env >= ENVELOPE_PERIOD(psg) * psg->step ) { psg->count_env = 0; psg->env_step--; /* check envelope current position */ if (psg->env_step < 0) { if (psg->hold) { if (psg->alternate) psg->attack ^= psg->env_step_mask; psg->holding = 1; psg->env_step = 0; } else { /* if CountEnv has looped an odd number of times (usually 1), */ /* invert the output. */ if (psg->alternate && (psg->env_step & (psg->env_step_mask + 1))) psg->attack ^= psg->env_step_mask; psg->env_step &= psg->env_step_mask; } } } } psg->env_volume = (psg->env_step ^ psg->attack); if (psg->streams == 3) { for (chan = 0; chan < NUM_CHANNELS; chan++) if (TONE_ENVELOPE(psg,chan)) { /* Envolope has no "off" state */ *(buf[chan]++) = psg->env_table[chan][psg->vol_enabled[chan] ? psg->env_volume : 0]; } else { *(buf[chan]++) = psg->vol_table[chan][psg->vol_enabled[chan] ? TONE_VOLUME(psg, chan) : 0]; } } else { *(buf[0]++) = mix_3D(psg); #if 0 *(buf[0]) = ( vol_enabled[0] * psg->vol_table[psg->Vol[0]] + vol_enabled[1] * psg->vol_table[psg->Vol[1]] + vol_enabled[2] * psg->vol_table[psg->Vol[2]]) / psg->step; #endif } length--; } }