예제 #1
0
        public bool FrameAdvance(IController controller, bool render, bool rendersound)
        {
            FrameAdvancePrep(controller);
            if (_syncSettings.EqualLengthFrames)
            {
                while (true)
                {
                    // target number of samples to emit: length of 1 frame minus whatever overflow
                    uint samplesEmitted = TICKSINFRAME - frameOverflow;
                    Debug.Assert(samplesEmitted * 2 <= _soundbuff.Length);
                    if (LibGambatte.gambatte_runfor(GambatteState, _soundbuff, ref samplesEmitted) > 0)
                    {
                        LibGambatte.gambatte_blitto(GambatteState, VideoBuffer, 160);
                    }

                    // account for actual number of samples emitted
                    _cycleCount   += samplesEmitted;
                    frameOverflow += samplesEmitted;

                    if (rendersound && !Muted)
                    {
                        ProcessSound((int)samplesEmitted);
                    }

                    if (frameOverflow >= TICKSINFRAME)
                    {
                        frameOverflow -= TICKSINFRAME;
                        break;
                    }
                }
            }
            else
            {
                // target number of samples to emit: always 59.7fps
                // runfor() always ends after creating a video frame, so sync-up is guaranteed
                // when the display has been off, some frames can be markedly shorter than expected
                uint samplesEmitted = TICKSINFRAME;
                if (LibGambatte.gambatte_runfor(GambatteState, _soundbuff, ref samplesEmitted) > 0)
                {
                    LibGambatte.gambatte_blitto(GambatteState, VideoBuffer, 160);
                }

                _cycleCount  += samplesEmitted;
                frameOverflow = 0;
                if (rendersound && !Muted)
                {
                    ProcessSound((int)samplesEmitted);
                }
            }

            if (rendersound && !Muted)
            {
                ProcessSoundEnd();
            }

            FrameAdvancePost();

            return(true);
        }
예제 #2
0
        public void FrameAdvance(bool render, bool rendersound = true)
        {
            LCont.Clear();
            RCont.Clear();

            foreach (var s in DualGbController.BoolButtons)
            {
                if (Controller.IsPressed(s))
                {
                    if (s.Contains("P1 "))
                    {
                        LCont.Set(s.Replace("P1 ", ""));
                    }
                    else if (s.Contains("P2 "))
                    {
                        RCont.Set(s.Replace("P2 ", ""));
                    }
                }
            }
            bool cablediscosignal_new = Controller.IsPressed("Toggle Cable");

            if (cablediscosignal_new && !cablediscosignal)
            {
                cableconnected ^= true;
                Console.WriteLine("Cable connect status to {0}", cableconnected);
                LinkConnected = cableconnected;
            }
            cablediscosignal = cablediscosignal_new;

            Frame++;
            L.FrameAdvancePrep();
            R.FrameAdvancePrep();

            unsafe
            {
                fixed(int *leftvbuff = &VideoBuffer[0])
                {
                    // use pitch to have both cores write to the same video buffer, interleaved
                    int *     rightvbuff = leftvbuff + 160;
                    const int pitch      = 160 * 2;

                    fixed(short *leftsbuff = LeftBuffer, rightsbuff = RightBuffer)
                    {
                        const int step = 32;                         // could be 1024 for GB

                        int nL = overflowL;
                        int nR = overflowR;

                        // slowly step our way through the frame, while continually checking and resolving link cable status
                        for (int target = 0; target < SampPerFrame;)
                        {
                            target += step;
                            if (target > SampPerFrame)
                            {
                                target = SampPerFrame;                                 // don't run for slightly too long depending on step
                            }
                            // gambatte_runfor() aborts early when a frame is produced, but we don't want that, hence the while()
                            while (nL < target)
                            {
                                uint nsamp = (uint)(target - nL);
                                if (LibGambatte.gambatte_runfor(L.GambatteState, leftsbuff + nL * 2, ref nsamp) > 0)
                                {
                                    LibGambatte.gambatte_blitto(L.GambatteState, leftvbuff, pitch);
                                }
                                nL += (int)nsamp;
                            }
                            while (nR < target)
                            {
                                uint nsamp = (uint)(target - nR);
                                if (LibGambatte.gambatte_runfor(R.GambatteState, rightsbuff + nR * 2, ref nsamp) > 0)
                                {
                                    LibGambatte.gambatte_blitto(R.GambatteState, rightvbuff, pitch);
                                }
                                nR += (int)nsamp;
                            }

                            // poll link cable statuses, but not when the cable is disconnected
                            if (!cableconnected)
                            {
                                continue;
                            }

                            if (LibGambatte.gambatte_linkstatus(L.GambatteState, 256) != 0)                            // ClockTrigger
                            {
                                LibGambatte.gambatte_linkstatus(L.GambatteState, 257);                                 // ack
                                int lo = LibGambatte.gambatte_linkstatus(L.GambatteState, 258);                        // GetOut
                                int ro = LibGambatte.gambatte_linkstatus(R.GambatteState, 258);
                                LibGambatte.gambatte_linkstatus(L.GambatteState, ro & 0xff);                           // ShiftIn
                                LibGambatte.gambatte_linkstatus(R.GambatteState, lo & 0xff);                           // ShiftIn
                            }
                            if (LibGambatte.gambatte_linkstatus(R.GambatteState, 256) != 0)                            // ClockTrigger
                            {
                                LibGambatte.gambatte_linkstatus(R.GambatteState, 257);                                 // ack
                                int lo = LibGambatte.gambatte_linkstatus(L.GambatteState, 258);                        // GetOut
                                int ro = LibGambatte.gambatte_linkstatus(R.GambatteState, 258);
                                LibGambatte.gambatte_linkstatus(L.GambatteState, ro & 0xff);                           // ShiftIn
                                LibGambatte.gambatte_linkstatus(R.GambatteState, lo & 0xff);                           // ShiftIn
                            }
                        }
                        overflowL = nL - SampPerFrame;
                        overflowR = nR - SampPerFrame;
                        if (overflowL < 0 || overflowR < 0)
                        {
                            throw new Exception("Timing problem?");
                        }

                        if (rendersound)
                        {
                            PrepSound();
                        }
                        // copy extra samples back to beginning
                        for (int i = 0; i < overflowL * 2; i++)
                        {
                            LeftBuffer[i] = LeftBuffer[i + SampPerFrame * 2];
                        }
                        for (int i = 0; i < overflowR * 2; i++)
                        {
                            RightBuffer[i] = RightBuffer[i + SampPerFrame * 2];
                        }
                    }
                }
            }

            L.FrameAdvancePost();
            R.FrameAdvancePost();
            IsLagFrame = L.IsLagFrame && R.IsLagFrame;
            if (IsLagFrame)
            {
                LagCount++;
            }
        }
예제 #3
0
        public bool FrameAdvance(IController controller, bool render, bool rendersound)
        {
            FrameAdvancePrep(controller);
            uint samplesEmitted;

            switch (_syncSettings.FrameLength)
            {
            case GambatteSyncSettings.FrameLengthType.VBlankDrivenFrames:
                // target number of samples to emit: always 59.7fps
                // runfor() always ends after creating a video frame, so sync-up is guaranteed
                // when the display has been off, some frames can be markedly shorter than expected
                samplesEmitted = TICKSINFRAME;
                if (LibGambatte.gambatte_runfor(GambatteState, _soundbuff, ref samplesEmitted) > 0)
                {
                    LibGambatte.gambatte_blitto(GambatteState, VideoBuffer, 160);
                }

                _cycleCount  += samplesEmitted;
                frameOverflow = 0;
                if (rendersound && !Muted)
                {
                    ProcessSound((int)samplesEmitted);
                }
                break;

            case GambatteSyncSettings.FrameLengthType.EqualLengthFrames:
                while (true)
                {
                    // target number of samples to emit: length of 1 frame minus whatever overflow
                    samplesEmitted = TICKSINFRAME - frameOverflow;
                    Debug.Assert(samplesEmitted * 2 <= _soundbuff.Length);
                    if (LibGambatte.gambatte_runfor(GambatteState, _soundbuff, ref samplesEmitted) > 0)
                    {
                        LibGambatte.gambatte_blitto(GambatteState, VideoBuffer, 160);
                    }

                    // account for actual number of samples emitted
                    _cycleCount   += samplesEmitted;
                    frameOverflow += samplesEmitted;

                    if (rendersound && !Muted)
                    {
                        ProcessSound((int)samplesEmitted);
                    }

                    if (frameOverflow >= TICKSINFRAME)
                    {
                        frameOverflow -= TICKSINFRAME;
                        break;
                    }
                }
                break;

            case GambatteSyncSettings.FrameLengthType.UserDefinedFrames:
                while (true)
                {
                    // target number of samples to emit: input length minus whatever overflow
                    float inputFrameLength    = controller.AxisValue("Input Length");
                    uint  inputFrameLengthInt = (uint)Math.Floor(inputFrameLength);
                    if (inputFrameLengthInt == 0)
                    {
                        inputFrameLengthInt = TICKSINFRAME;
                    }
                    samplesEmitted = inputFrameLengthInt - frameOverflow;
                    Debug.Assert(samplesEmitted * 2 <= _soundbuff.Length);
                    if (LibGambatte.gambatte_runfor(GambatteState, _soundbuff, ref samplesEmitted) > 0)
                    {
                        LibGambatte.gambatte_blitto(GambatteState, VideoBuffer, 160);
                    }

                    // account for actual number of samples emitted
                    _cycleCount   += samplesEmitted;
                    frameOverflow += samplesEmitted;

                    if (rendersound && !Muted)
                    {
                        ProcessSound((int)samplesEmitted);
                    }

                    if (frameOverflow >= inputFrameLengthInt)
                    {
                        frameOverflow -= inputFrameLengthInt;
                        break;
                    }
                }
                break;
            }

            if (rendersound && !Muted)
            {
                ProcessSoundEnd();
            }

            FrameAdvancePost();

            return(true);
        }