示例#1
0
        /// <summary>
        /// Processes an incoming pulse value and adds it to the blipbuffer
        /// </summary>
        /// <param name="pulse"></param>
        public void ProcessPulseValue(bool pulse)
        {
            if (!_machine._renderSound)
            {
                return;
            }

            if (LastPulse == pulse)
            {
                // no change
                blip.AddDelta((uint)_machine.CurrentFrameCycle, 0);
            }

            else
            {
                if (pulse)
                {
                    blip.AddDelta((uint)_machine.CurrentFrameCycle, (short)(_volume));
                }
                else
                {
                    blip.AddDelta((uint)_machine.CurrentFrameCycle, -(short)(_volume));
                }

                lastVolume = _volume;
            }

            LastPulse = pulse;
        }
示例#2
0
        private void ProcessSound(int nsamp)
        {
            for (uint i = 0; i < nsamp; i++)
            {
                int curr = _soundbuff[i * 2];

                if (curr != _latchL)
                {
                    int diff = _latchL - curr;
                    _latchL = curr;
                    _blipL.AddDelta(_blipAccumulate, diff >> 2);
                }

                curr = _soundbuff[(i * 2) + 1];

                if (curr != _latchR)
                {
                    int diff = _latchR - curr;
                    _latchR = curr;
                    _blipR.AddDelta(_blipAccumulate, diff >> 2);
                }

                _blipAccumulate++;
            }
        }
示例#3
0
        /// <summary>
        /// Processes an incoming pulse value
        /// </summary>
        public void ProcessPulseValue(bool pulse, bool renderSound = true)
        {
            if (!renderSound)
            {
                return;
            }

            if (lastPulse == pulse)
            {
                // no change
                _blip.AddDelta((uint)clockCounter, 0);
            }

            else
            {
                if (pulse)
                {
                    _blip.AddDelta((uint)clockCounter, (short)(_volume));
                }
                else
                {
                    _blip.AddDelta((uint)clockCounter, -(short)(_volume));
                }

                lastVolume = _volume;
            }

            lastPulse = pulse;
        }
示例#4
0
文件: Core.cs 项目: stuff2600/RAEmus
            public void GetSamples(short[] samples)
            {
                //Console.WriteLine("Sync: {0}", nes.apu.dlist.Count);
                int nsamp = samples.Length / 2;

                if (nsamp > blipbuffsize)                 // oh well.
                {
                    nsamp = blipbuffsize;
                }
                uint targetclock = (uint)blip.ClocksNeeded(nsamp);
                uint actualclock = nes.apu.sampleclock;

                foreach (var d in nes.apu.dlist)
                {
                    blip.AddDelta(d.time * targetclock / actualclock, d.value);
                }
                nes.apu.dlist.Clear();
                blip.EndFrame(targetclock);
                nes.apu.sampleclock = 0;

                blip.ReadSamples(samples, nsamp, true);
                // duplicate to stereo
                for (int i = 0; i < nsamp * 2; i += 2)
                {
                    samples[i + 1] = samples[i];
                }

                //mix in the cart's extra sound circuit
                nes.board.ApplyCustomAudio(samples);
            }
        private void ProcessSound(int nsamp)
        {
            for (uint i = 0; i < nsamp; i++)
            {
                int curr = soundbuff[i * 2];

                if (curr != latchL)
                {
                    int diff = latchL - curr;
                    latchL = curr;
                    blipL.AddDelta(blipAccumulate, diff);
                }

                curr = soundbuff[i * 2 + 1];

                if (curr != latchR)
                {
                    int diff = latchR - curr;
                    latchR = curr;
                    blipR.AddDelta(blipAccumulate, diff);
                }

                blipAccumulate++;
            }
        }
示例#6
0
        public void tick()
        {
            // add up components to each channel
            int L_final = 0;
            int R_final = 0;

            if (AUD_CTRL_sq1_L_en)
            {
                L_final += 0;
            }


            if (AUD_CTRL_sq1_R_en)
            {
                R_final += 0;
            }

            L_final *= (AUD_CTRL_vol_L + 1) * 40;
            R_final *= (AUD_CTRL_vol_R + 1) * 40;

            if (L_final != latched_sample_L)
            {
                _blip_L.AddDelta(master_audio_clock, L_final - latched_sample_L);
                latched_sample_L = L_final;
            }

            if (R_final != latched_sample_R)
            {
                _blip_R.AddDelta(master_audio_clock, R_final - latched_sample_R);
                latched_sample_R = R_final;
            }

            master_audio_clock++;
        }
示例#7
0
        unsafe void PrepSound()
        {
            fixed(short *sl = LeftBuffer, sr = RightBuffer)
            {
                for (uint i = 0; i < SampPerFrame * 2; i += 2)
                {
                    int s = (sl[i] + sl[i + 1]) / 2;
                    if (s != LatchL)
                    {
                        blip_left.AddDelta(i, s - LatchL);
                        LatchL = s;
                    }
                    s = (sr[i] + sr[i + 1]) / 2;
                    if (s != LatchR)
                    {
                        blip_right.AddDelta(i, s - LatchR);
                        LatchR = s;
                    }
                }
            }

            blip_left.EndFrame(SampPerFrame * 2);
            blip_right.EndFrame(SampPerFrame * 2);
            int count = blip_left.SamplesAvailable();

            if (count != blip_right.SamplesAvailable())
            {
                throw new Exception("Sound problem?");
            }

            // calling blip.Clear() causes rounding fractions to be reset,
            // and if only one channel is muted, in subsequent frames we can be off by a sample or two
            // not a big deal, but we didn't account for it.  so we actually complete the entire
            // audio read and then stamp it out if muted.

            blip_left.ReadSamplesLeft(SampleBuffer, count);
            if (L.Muted)
            {
                fixed(short *p = SampleBuffer)
                {
                    for (int i = 0; i < SampleBuffer.Length; i += 2)
                    {
                        p[i] = 0;
                    }
                }
            }

            blip_right.ReadSamplesRight(SampleBuffer, count);
            if (R.Muted)
            {
                fixed(short *p = SampleBuffer)
                {
                    for (int i = 1; i < SampleBuffer.Length; i += 2)
                    {
                        p[i] = 0;
                    }
                }
            }
            SampleBufferContains = count;
        }
示例#8
0
        public void Audio_tick()
        {
            int C_final = 0;

            if (aud_ctrl.Bit(7))
            {
                tick_cnt++;
                if (tick_cnt > (aud_ctrl.Bit(5) ? 455 : 1820))
                {
                    tick_cnt = 0;

                    output_bit = shift_2 & 1;

                    shift_2 = (byte)((shift_2 >> 1) | ((shift_1 & 1) << 7));
                    shift_1 = (byte)((shift_1 >> 1) | ((shift_0 & 1) << 7));

                    if (aud_ctrl.Bit(6))
                    {
                        shift_0 = (byte)((shift_0 >> 1) | (output_bit << 7));
                    }
                    else
                    {
                        shift_0 = (byte)(shift_0 >> 1);
                    }

                    if (aud_ctrl.Bit(4))
                    {
                        if (shift_2.Bit(7) == output_bit.Bit(0))
                        {
                            shift_2 &= 0x7F;
                        }
                        else
                        {
                            shift_2 = (byte)(shift_2 | 0x80);
                        }
                    }
                }

                C_final  = output_bit;
                C_final *= ((aud_ctrl & 0xF) + 1) * 3200;
            }

            if (C_final != latched_sample_C)
            {
                _blip_C.AddDelta(master_audio_clock, C_final - latched_sample_C);
                latched_sample_C = C_final;
            }

            master_audio_clock++;
        }
示例#9
0
        public void GetSamplesSync(out short[] samples, out int nsamp)
        {
            uint f_clock = LibMSX.MSX_get_audio(MSX_Pntr, Aud, ref num_samp);

            for (int i = 0; i < num_samp; i++)
            {
                blip.AddDelta((uint)Aud[i * 2], Aud[i * 2 + 1]);
            }

            blip.EndFrame(f_clock);

            nsamp   = blip.SamplesAvailable();
            samples = new short[nsamp * 2];

            blip.ReadSamples(samples, nsamp, true);
        }
        private void ProcessSound()
        {
            var len = bridge.LibretroBridge_GetAudioSize(cbHandler);

            if (len == 0)             // no audio?
            {
                return;
            }
            if (len > _inSampBuf.Length)
            {
                _inSampBuf = new short[len];
            }
            var ns = 0;

            bridge.LibretroBridge_GetAudio(cbHandler, ref ns, _inSampBuf);

            for (uint i = 0; i < ns; i++)
            {
                int curr = _inSampBuf[i * 2];

                if (curr != _latchL)
                {
                    int diff = _latchL - curr;
                    _latchL = curr;
                    _blipL.AddDelta(i, diff);
                }

                curr = _inSampBuf[(i * 2) + 1];

                if (curr != _latchR)
                {
                    int diff = _latchR - curr;
                    _latchR = curr;
                    _blipR.AddDelta(i, diff);
                }
            }

            _blipL.EndFrame((uint)ns);
            _blipR.EndFrame((uint)ns);
            _outSamps = _blipL.SamplesAvailable();
            _blipL.ReadSamplesLeft(_outSampBuf, _outSamps);
            _blipR.ReadSamplesRight(_outSampBuf, _outSamps);
        }
示例#11
0
            public void GetSamplesSync(out short[] samples, out int nsamp)
            {
                //Console.WriteLine("ASync: {0}", nes.apu.dlist.Count);
                foreach (var d in nes.apu.dlist)
                {
                    blip.AddDelta(d.time, d.value);
                }
                nes.apu.dlist.Clear();
                blip.EndFrame(nes.apu.sampleclock);
                nes.apu.sampleclock = 0;

                nsamp   = blip.SamplesAvailable();
                samples = new short[nsamp * 2];

                blip.ReadSamples(samples, nsamp, true);
                // duplicate to stereo
                for (int i = 0; i < nsamp * 2; i += 2)
                {
                    samples[i + 1] = samples[i];
                }

                nes.Board.ApplyCustomAudio(samples);
            }
示例#12
0
        public void GetSamplesSync(out short[] samples, out int nsamp)
        {
            uint f_clock = LibMSX.MSX_get_audio(MSX_Pntr, Aud_L, Aud_R, ref num_samp_L, ref num_samp_R);

            for (int i = 0; i < num_samp_L; i++)
            {
                blip_L.AddDelta(Aud_L[i * 2], (int)Aud_L[i * 2 + 1]);
            }

            for (int i = 0; i < num_samp_R; i++)
            {
                blip_R.AddDelta(Aud_R[i * 2], (int)Aud_R[i * 2 + 1]);
            }

            blip_L.EndFrame(f_clock);
            blip_R.EndFrame(f_clock);

            nsamp   = Math.Max(Math.Max(blip_L.SamplesAvailable(), blip_R.SamplesAvailable()), 1);
            samples = new short[nsamp * 2];

            blip_L.ReadSamplesLeft(samples, nsamp);
            blip_R.ReadSamplesRight(samples, nsamp);
        }
示例#13
0
        private void AudioChange()
        {
            if (tone == 0)
            {
                // silence
            }
            else
            {
                int    SamplesPerWave = (int)(SampleRate / tone_freqs[tone]);
                double RadPerSample   = (Math.PI * 2) / (double)SamplesPerWave;
                double SinVal         = 0;

                int NumSamples = (int)(((double)FrameClock - (double)lastCycle) / CyclesPerSample);

                int startPos = lastCycle;

                for (int i = 0; i < NumSamples; i++)
                {
                    SinVal = Math.Sin(RadPerSample * (double)(i * SamplesPerWave));
                    _blip.AddDelta((uint)startPos, (int)(Math.Floor(SinVal * 127) + 128) * 1024);
                    startPos += (int)CyclesPerSample;
                }
            }
        }
示例#14
0
        public byte DB;                 //old data bus values from previous reads

        internal void RunCpuOne()
        {
            ///////////////////////////
            // OAM DMA start
            ///////////////////////////

            if (oam_dma_exec && apu.dmc_dma_countdown != 1 && !dmc_realign)
            {
                if (cpu_deadcounter == 0)
                {
                    if (oam_dma_index % 2 == 0)
                    {
                        oam_dma_byte = ReadMemory(oam_dma_addr);
                        oam_dma_addr++;
                    }
                    else
                    {
                        WriteMemory(0x2004, oam_dma_byte);
                    }
                    oam_dma_index++;
                    if (oam_dma_index == 512)
                    {
                        oam_dma_exec = false;
                    }
                }
                else
                {
                    cpu_deadcounter--;
                }
            }

            dmc_realign = false;

            /////////////////////////////
            // OAM DMA end
            /////////////////////////////


            /////////////////////////////
            // dmc dma start
            /////////////////////////////

            if (apu.dmc_dma_countdown > 0)
            {
                if (apu.dmc_dma_countdown == 1)
                {
                    dmc_realign = true;
                }

                // By this point the cpu should be frozen, if it is not, then we are in a multi-write opcode, add another cycle delay
                if (!cpu.RDY && !cpu.rdy_freeze && (apu.dmc_dma_countdown == apu.DMC_RDY_check))
                {
                    //Console.WriteLine("dmc RDY false " + cpu.TotalExecutedCycles + " " + apu.call_from_write + " " + cpu.opcode + " " + oam_dma_exec);
                    apu.dmc_dma_countdown += 2;
                    apu.DMC_RDY_check      = -1;
                }

                cpu.RDY      = false;
                dmc_dma_exec = true;
                apu.dmc_dma_countdown--;
                if (apu.dmc_dma_countdown == 0)
                {
                    apu.RunDMCFetch();
                    dmc_dma_exec          = false;
                    apu.dmc_dma_countdown = -1;
                    do_the_reread         = true;
                }

                //Console.WriteLine("dmc RDY false " + cpu.TotalExecutedCycles + " " + apu.call_from_write + " " + cpu.opcode);
            }

            /////////////////////////////
            // dmc dma end
            /////////////////////////////
            apu.RunOneFirst();

            if (cpu.RDY && !IRQ_delay)
            {
                cpu.IRQ = _irq_apu || Board.IrqSignal;
            }
            else if (special_case_delay || apu.dmc_dma_countdown == 3)
            {
                cpu.IRQ            = _irq_apu || Board.IrqSignal;
                special_case_delay = false;
            }

            cpu.ExecuteOne();
            Board.ClockCpu();

            int s = apu.EmitSample();

            if (s != old_s)
            {
                blip.AddDelta(apu.sampleclock, s - old_s);
                old_s = s;
            }
            apu.sampleclock++;

            apu.RunOneLast();

            if (do_the_reread && cpu.RDY)
            {
                do_the_reread = false;
            }

            IRQ_delay = false;

            if (!dmc_dma_exec && !oam_dma_exec && !cpu.RDY)
            {
                cpu.RDY   = true;
                IRQ_delay = true;
            }
        }
示例#15
0
        public byte DB;         //old data bus values from previous reads

        internal void RunCpuOne()
        {
            ///////////////////////////
            // OAM DMA start
            ///////////////////////////

            if (oam_dma_exec && apu.dmc_dma_countdown != 1 && !dmc_realign)
            {
                if (cpu_deadcounter == 0)
                {
                    if (oam_dma_index % 2 == 0)
                    {
                        oam_dma_byte = ReadMemory(oam_dma_addr);
                        oam_dma_addr++;
                    }
                    else
                    {
                        WriteMemory(0x2004, oam_dma_byte);
                    }
                    oam_dma_index++;
                    if (oam_dma_index == 512)
                    {
                        oam_dma_exec = false;
                    }
                }
                else
                {
                    cpu_deadcounter--;
                }
            }

            dmc_realign = false;

            /////////////////////////////
            // OAM DMA end
            /////////////////////////////


            /////////////////////////////
            // dmc dma start
            /////////////////////////////

            if (apu.dmc_dma_countdown > 0)
            {
                if (apu.dmc_dma_countdown == 1 && !apu.dmc.fill_glitch)
                {
                    dmc_realign = true;
                }

                // By this point the cpu should be frozen, if it is not, then we are in a multi-write opcode, add another cycle delay
                if (!cpu.RDY && !cpu.rdy_freeze && (apu.dmc_dma_countdown == apu.DMC_RDY_check))
                {
                    //Console.WriteLine("dmc double " + cpu.TotalExecutedCycles + " " + cpu.opcode + " " + cpu.mi);
                    apu.dmc_dma_countdown += 2;
                    apu.DMC_RDY_check      = -1;
                }

                cpu.RDY      = false;
                dmc_dma_exec = true;
                apu.dmc_dma_countdown--;
                if (apu.dmc_dma_countdown == 0)
                {
                    if (!apu.dmc.fill_glitch)
                    {
                        reread_trigger = true;
                        // if the DMA address has the same bits set as the re-read address, they don't occur
                        if ((apu.dmc.sample_address & 0x2007) != 0x2002)
                        {
                            do_the_reread_2002++;
                        }

                        if ((apu.dmc.sample_address & 0x2007) != 0x2007)
                        {
                            do_the_reread_2007++;
                        }

                        if ((apu.dmc.sample_address & 0x401F) != 0x4016)
                        {
                            do_the_reread_cont_1++;
                        }

                        if ((apu.dmc.sample_address & 0x401F) != 0x4017)
                        {
                            do_the_reread_cont_2++;
                        }

                        apu.RunDMCFetch();
                    }

                    dmc_dma_exec          = false;
                    apu.dmc_dma_countdown = -1;
                    apu.dmc.fill_glitch   = false;

                    /*
                     * //if (apu.dmc.timer == (apu.dmc.timer_reload-0) && apu.dmc.out_bits_remaining == 7)
                     * //if (apu.dmc.timer == 2 && apu.dmc.out_bits_remaining == 0)
                     * {
                     *      Console.WriteLine("close " + cpu.TotalExecutedCycles + " " + apu.dmc.timer + " " + apu.dmc.sample_length);
                     *      apu.dmc.fill_glitch = true;
                     *      apu.dmc.delay = 3;
                     * }
                     */
                    //Console.WriteLine("dmc RDY false " + cpu.TotalExecutedCycles + " " + cpu.opcode + " " + cpu.mi + " " + apu.dmc.timer);
                }
            }

            /////////////////////////////
            // dmc dma end
            /////////////////////////////
            apu.RunOneFirst();

            if (cpu.RDY && !IRQ_delay)
            {
                cpu.IRQ = _irq_apu || Board.IrqSignal;
            }
            else if (special_case_delay || apu.dmc_dma_countdown == 3)
            {
                cpu.IRQ = _irq_apu || Board.IrqSignal;
                //if (cpu.IRQ) { Console.WriteLine("something IRQ"); }
                special_case_delay = false;
            }

            cpu.ExecuteOne();
            Board.ClockCpu();

            int s = apu.EmitSample();

            if (s != old_s)
            {
                blip.AddDelta(apu.sampleclock, s - old_s);
                old_s = s;
            }
            apu.sampleclock++;

            apu.RunOneLast();

            if (reread_trigger && cpu.RDY)
            {
                do_the_reread_2002   = 0;
                do_the_reread_2007   = 0;
                do_the_reread_cont_1 = 0;
                do_the_reread_cont_2 = 0;
                reread_trigger       = false;
            }


            IRQ_delay = false;

            if (!dmc_dma_exec && !oam_dma_exec && !cpu.RDY)
            {
                cpu.RDY   = true;
                IRQ_delay = true;
            }
        }
示例#16
0
        public void tick()
        {
            // there are 8 cpu cycles for every psg cycle
            bool sound_out_A;
            bool sound_out_B;
            bool sound_out_C;

            psg_clock++;
            master_audio_clock++;

            if (psg_clock == 8)
            {
                psg_clock = 0;

                clock_A--;
                clock_B--;
                clock_C--;

                noise_clock--;
                env_clock--;

                // clock noise
                if (noise_clock == 0)
                {
                    noise       = (noise >> 1) ^ (noise.Bit(0) ? 0x10004 : 0);
                    noise_clock = noise_per;
                }

                if (env_clock == 0)
                {
                    env_clock = env_per;

                    env_E += E_up_down;

                    if (env_E == 16 || env_E == -1)
                    {
                        // we just completed a period of the envelope, determine what to do now based on the envelope shape
                        if (env_shape == 0 || env_shape == 1 || env_shape == 3 || env_shape == 9)
                        {
                            E_up_down = 0;
                            env_E     = 0;
                        }
                        else if (env_shape == 5 || env_shape == 7)
                        {
                            E_up_down = 0;
                            env_E     = 15;
                        }
                        else if (env_shape == 4 || env_shape == 8)
                        {
                            if (env_E == 16)
                            {
                                env_E     = 15;
                                E_up_down = -1;
                            }
                            else
                            {
                                env_E     = 0;
                                E_up_down = 1;
                            }
                        }
                        else if (env_shape == 2)
                        {
                            env_E = 15;
                        }
                        else
                        {
                            env_E = 0;
                        }
                    }
                }

                if (clock_A == 0)
                {
                    A_up    = !A_up;
                    clock_A = sq_per_A;
                }

                if (clock_B == 0)
                {
                    B_up    = !B_up;
                    clock_B = sq_per_B;
                }

                if (clock_C == 0)
                {
                    C_up    = !C_up;
                    clock_C = sq_per_C;
                }


                sound_out_A = (noise.Bit(0) | A_noise) & (A_on | A_up);
                sound_out_B = (noise.Bit(0) | B_noise) & (B_on | B_up);
                sound_out_C = (noise.Bit(0) | C_noise) & (C_on | C_up);

                // now calculate the volume of each channel and add them together
                int v;

                if (env_vol_A == 0)
                {
                    v = (short)(sound_out_A ? VolumeTable[vol_A] : 0);
                }
                else
                {
                    v = (short)(sound_out_A ? VolumeTable[vol_A] : 0);
                }

                if (env_vol_B == 0)
                {
                    v += (short)(sound_out_B ? VolumeTable[vol_B] : 0);
                }
                else
                {
                    v += (short)(sound_out_B ? VolumeTable[env_E] : 0);
                }

                if (env_vol_C == 0)
                {
                    v += (short)(sound_out_C ? VolumeTable[vol_C] : 0);
                }
                else
                {
                    v += (short)(sound_out_C ? VolumeTable[env_E] : 0);
                }

                current_sample = (short)v;

                if (current_sample != old_sample)
                {
                    _blip.AddDelta(master_audio_clock, current_sample - old_sample);
                    old_sample = current_sample;
                }
            }
        }
示例#17
0
        public void generate_sound(int cycles_to_do)
        {
            // there are 4 cpu cycles for every psg cycle
            bool sound_out_A;
            bool sound_out_B;
            bool sound_out_C;

            for (int i = 0; i < cycles_to_do; i++)
            {
                psg_clock++;

                if (psg_clock == 4)
                {
                    psg_clock = 0;

                    total_clock++;

                    clock_A--;
                    clock_B--;
                    clock_C--;

                    noise_clock--;
                    env_clock--;

                    // clock noise
                    if (noise_clock == 0)
                    {
                        noise       = (noise >> 1) ^ (noise.Bit(0) ? 0x10004 : 0);
                        noise_clock = noise_per;
                    }

                    if (env_clock == 0)
                    {
                        env_clock = env_per;

                        env_E += E_up_down;

                        if (env_E == 16 || env_E == -1)
                        {
                            // we just completed a period of the envelope, determine what to do now based on the envelope shape
                            if (env_shape == 0 || env_shape == 1 || env_shape == 3 || env_shape == 9)
                            {
                                E_up_down = 0;
                                env_E     = 0;
                            }
                            else if (env_shape == 5 || env_shape == 7)
                            {
                                E_up_down = 0;
                                env_E     = 15;
                            }
                            else if (env_shape == 4 || env_shape == 8)
                            {
                                if (env_E == 16)
                                {
                                    env_E     = 15;
                                    E_up_down = -1;
                                }
                                else
                                {
                                    env_E     = 0;
                                    E_up_down = 1;
                                }
                            }
                            else if (env_shape == 2)
                            {
                                env_E = 15;
                            }
                            else
                            {
                                env_E = 0;
                            }
                        }
                    }

                    if (clock_A == 0)
                    {
                        A_up    = !A_up;
                        clock_A = sq_per_A;
                    }

                    if (clock_B == 0)
                    {
                        B_up    = !B_up;
                        clock_B = sq_per_B;
                    }

                    if (clock_C == 0)
                    {
                        C_up    = !C_up;
                        clock_C = sq_per_C;
                    }


                    sound_out_A = (noise.Bit(0) | A_noise) & (A_on | A_up);
                    sound_out_B = (noise.Bit(0) | B_noise) & (B_on | B_up);
                    sound_out_C = (noise.Bit(0) | C_noise) & (C_on | C_up);

                    // now calculate the volume of each channel and add them together
                    int v;

                    if (env_vol_A == 0)
                    {
                        v = (short)(sound_out_A ? VolumeTable[vol_A] : 0);
                    }
                    else
                    {
                        int shift_A = 3 - env_vol_A;
                        if (shift_A < 0)
                        {
                            shift_A = 0;
                        }
                        v = (short)(sound_out_A ? (VolumeTable[env_E] >> shift_A) : 0);
                    }

                    if (env_vol_B == 0)
                    {
                        v += (short)(sound_out_B ? VolumeTable[vol_B] : 0);
                    }
                    else
                    {
                        int shift_B = 3 - env_vol_B;
                        if (shift_B < 0)
                        {
                            shift_B = 0;
                        }
                        v += (short)(sound_out_B ? (VolumeTable[env_E] >> shift_B) : 0);
                    }

                    if (env_vol_C == 0)
                    {
                        v += (short)(sound_out_C ? VolumeTable[vol_C] : 0);
                    }
                    else
                    {
                        int shift_C = 3 - env_vol_C;
                        if (shift_C < 0)
                        {
                            shift_C = 0;
                        }
                        v += (short)(sound_out_C ? (VolumeTable[env_E] >> shift_C) : 0);
                    }

                    if (v != _latchedSample)
                    {
                        _blip.AddDelta((uint)_sampleClock, v - _latchedSample);
                        _latchedSample = v;
                    }

                    _sampleClock++;
                }
            }
        }
示例#18
0
        public byte DB;                 //old data bus values from previous reads

        internal void RunCpuOne()
        {
            ///////////////////////////
            // OAM DMA start
            ///////////////////////////

            if (sprdma_countdown > 0)
            {
                sprdma_countdown--;
                if (sprdma_countdown == 0)
                {
                    if (cpu.TotalExecutedCycles % 2 == 0)
                    {
                        cpu_deadcounter = 2;
                    }
                    else
                    {
                        cpu_deadcounter = 1;
                    }
                    oam_dma_exec       = true;
                    cpu.RDY            = false;
                    oam_dma_index      = 0;
                    special_case_delay = true;
                }
            }

            if (oam_dma_exec && apu.dmc_dma_countdown != 1 && !dmc_realign)
            {
                if (cpu_deadcounter == 0)
                {
                    if (oam_dma_index % 2 == 0)
                    {
                        oam_dma_byte = ReadMemory(oam_dma_addr);
                        oam_dma_addr++;
                    }
                    else
                    {
                        WriteMemory(0x2004, oam_dma_byte);
                    }
                    oam_dma_index++;
                    if (oam_dma_index == 512)
                    {
                        oam_dma_exec = false;
                    }
                }
                else
                {
                    cpu_deadcounter--;
                }
            }
            else if (apu.dmc_dma_countdown == 1)
            {
                dmc_realign = true;
            }
            else if (dmc_realign)
            {
                dmc_realign = false;
            }
            /////////////////////////////
            // OAM DMA end
            /////////////////////////////


            /////////////////////////////
            // dmc dma start
            /////////////////////////////

            if (apu.dmc_dma_countdown > 0)
            {
                cpu.RDY      = false;
                dmc_dma_exec = true;
                apu.dmc_dma_countdown--;
                if (apu.dmc_dma_countdown == 0)
                {
                    apu.RunDMCFetch();
                    dmc_dma_exec          = false;
                    apu.dmc_dma_countdown = -1;
                    do_the_reread         = true;
                }
            }

            /////////////////////////////
            // dmc dma end
            /////////////////////////////
            apu.RunOneFirst();

            if (cpu.RDY && !IRQ_delay)
            {
                cpu.IRQ = _irq_apu || Board.IRQSignal;
            }
            else if (special_case_delay || apu.dmc_dma_countdown == 3)
            {
                cpu.IRQ            = _irq_apu || Board.IRQSignal;
                special_case_delay = false;
            }

            cpu.ExecuteOne();
            Board.ClockCPU();

            int s = apu.EmitSample();

            if (s != old_s)
            {
                blip.AddDelta(apu.sampleclock, s - old_s);
                old_s = s;
            }
            apu.sampleclock++;

            apu.RunOneLast();

            if (ppu.double_2007_read > 0)
            {
                ppu.double_2007_read--;
            }

            if (do_the_reread && cpu.RDY)
            {
                do_the_reread = false;
            }

            if (IRQ_delay)
            {
                IRQ_delay = false;
            }

            if (!dmc_dma_exec && !oam_dma_exec && !cpu.RDY)
            {
                cpu.RDY   = true;
                IRQ_delay = true;
            }
        }