From 121cd4fb58821fd5b0a995b4b9e496cdac567cba Mon Sep 17 00:00:00 2001 From: adelikat Date: Thu, 7 Nov 2013 17:11:08 +0000 Subject: [PATCH] Oops, throttle is not a good thing to put into Client.Common, it has window specific things --- .../BizHawk.Client.Common.csproj | 1 - BizHawk.Client.Common/Throttle.cs | 374 ------------------ .../BizHawk.Client.EmuHawk.csproj | 1 + 3 files changed, 1 insertion(+), 375 deletions(-) delete mode 100644 BizHawk.Client.Common/Throttle.cs diff --git a/BizHawk.Client.Common/BizHawk.Client.Common.csproj b/BizHawk.Client.Common/BizHawk.Client.Common.csproj index afc95dbefc..e1128b92bb 100644 --- a/BizHawk.Client.Common/BizHawk.Client.Common.csproj +++ b/BizHawk.Client.Common/BizHawk.Client.Common.csproj @@ -135,7 +135,6 @@ - diff --git a/BizHawk.Client.Common/Throttle.cs b/BizHawk.Client.Common/Throttle.cs deleted file mode 100644 index 666f2ab2e0..0000000000 --- a/BizHawk.Client.Common/Throttle.cs +++ /dev/null @@ -1,374 +0,0 @@ -using System; -using System.Threading; - -//this throttle is nitsuja's fine-tuned techniques from desmume - -namespace BizHawk.Client.Common -{ - public class Throttle - { - int lastskiprate; - int framestoskip; - int framesskipped; - public bool skipnextframe; - - //if the emulator is paused then we dont need to behave as if unthrottled - public bool signal_paused; - public bool signal_frameAdvance; - public bool signal_unthrottle; - public bool signal_continuousframeAdvancing; //continuousframeAdvancing - - public int cfg_frameskiprate - { - get - { - if (Global.ClientControls["MaxTurbo"]) - { - return 20; - } - else - { - return Global.Config.FrameSkip; - } - } - } - public bool cfg_frameLimit - { - get - { - if (Global.ClientControls["MaxTurbo"]) - { - return false; - } - else - { - return Global.Config.ClockThrottle; - } - } - } - - public bool cfg_autoframeskipenab - { - get - { - if (Global.ClientControls["MaxTurbo"]) - { - return false; - } - else - { - return Global.Config.AutoMinimizeSkipping; - } - } - } - - public void Step(bool allowSleep, int forceFrameSkip) - { - int skipRate = (forceFrameSkip < 0) ? cfg_frameskiprate : forceFrameSkip; - int ffSkipRate = (forceFrameSkip < 0) ? 3 : forceFrameSkip; - - if (lastskiprate != skipRate) - { - lastskiprate = skipRate; - framestoskip = 0; // otherwise switches to lower frameskip rates will lag behind - } - - if (!skipnextframe || forceFrameSkip == 0 || signal_frameAdvance || (signal_continuousframeAdvancing && !signal_unthrottle)) - { - framesskipped = 0; - - if (framestoskip > 0) - skipnextframe = true; - } - else - { - framestoskip--; - - if (framestoskip < 1) - skipnextframe = false; - else - skipnextframe = true; - - framesskipped++; - - //NDS_SkipNextFrame(); - } - - if (signal_unthrottle) - { - if (framesskipped < ffSkipRate) - { - skipnextframe = true; - framestoskip = 1; - } - if (framestoskip < 1) - framestoskip += ffSkipRate; - } - else if ((signal_paused || /*autoframeskipenab && frameskiprate ||*/ cfg_frameLimit) && allowSleep) - { - SpeedThrottle(signal_paused); - } - - if (cfg_autoframeskipenab && cfg_frameskiprate != 0) - { - if (!signal_frameAdvance && !signal_continuousframeAdvancing) - { - AutoFrameSkip_NextFrame(); - if (framestoskip < 1) - framestoskip += AutoFrameSkip_GetSkipAmount(0, skipRate); - } - } - else - { - if (framestoskip < 1) - framestoskip += skipRate; - } - - if (signal_frameAdvance && allowSleep) - { - //this logic has been replaced by some logic in steprunloop_core. - //really, it should be moved back here somehow later. - - //frameAdvance = false; - //emu_halt(); - //SPU_Pause(1); - } - //if (execute && emu_paused && !frameAdvance) - //{ - // // safety net against running out of control in case this ever happens. - // Unpause(); Pause(); - //} - } - - static ulong GetCurTime() - { -#if WINDOWS - if (tmethod == 1) - { - ulong tmp; - QueryPerformanceCounter(out tmp); - return tmp; - } - else - { -#endif - return (ulong)Environment.TickCount; -#if WINDOWS - } -#endif - } - - -#if WINDOWS - [DllImport("kernel32.dll", SetLastError = true)] - static extern bool QueryPerformanceCounter(out ulong lpPerformanceCount); - - [DllImport("kernel32.dll", SetLastError = true)] - static extern bool QueryPerformanceFrequency(out ulong frequency); - - [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")] - static extern uint timeBeginPeriod(uint uMilliseconds); - - static readonly int tmethod; -#endif - - static readonly ulong afsfreq; - static readonly ulong tfreq; - - static Throttle() - { -#if WINDOWS - timeBeginPeriod(1); - tmethod = 0; - if (QueryPerformanceFrequency(out afsfreq)) - tmethod = 1; - else - afsfreq = 1000; - Console.WriteLine("throttle method: {0}; resolution: {1}", tmethod, afsfreq); -#else - afsfreq = 1000; -#endif - tfreq = afsfreq << 16; - } - - public void SetCoreFps(double desired_fps) - { - core_desiredfps = (ulong)(65536 * desired_fps); - int target_pct = pct; - pct = -1; - SetSpeedPercent(target_pct); - } - - int pct = -1; - public void SetSpeedPercent(int percent) - { - //Console.WriteLine("throttle set percent " + percent); - if (pct == percent) return; - pct = percent; - float fraction = percent / 100.0f; - desiredfps = (ulong)(core_desiredfps * fraction); - //Console.WriteLine("throttle set desiredfps " + desiredfps); - desiredspf = 65536.0f / desiredfps; - AutoFrameSkip_IgnorePreviousDelay(); - } - - ulong core_desiredfps; - ulong desiredfps; - float desiredspf; - - ulong ltime; - ulong beginticks, endticks, preThrottleEndticks; - float fSkipFrames; - float fSkipFramesError; - int lastSkip; - float lastError; - float integral; - - public void AutoFrameSkip_IgnorePreviousDelay() - { - beginticks = GetCurTime(); - - // this seems to be a stable way of allowing the skip frames to - // quickly adjust to a faster environment (e.g. after a loadstate) - // without causing oscillation or a sudden change in skip rate - fSkipFrames *= 0.5f; - } - - void AutoFrameSkip_BeforeThrottle() - { - preThrottleEndticks = GetCurTime(); - } - - void AutoFrameSkip_NextFrame() - { - endticks = GetCurTime(); - - // calculate time since last frame - ulong diffticks = endticks - beginticks; - float diff = (float)diffticks / afsfreq; - - // calculate time since last frame not including throttle sleep time - if (preThrottleEndticks == 0) // if we didn't throttle, use the non-throttle time - preThrottleEndticks = endticks; - ulong diffticksUnthrottled = preThrottleEndticks - beginticks; - float diffUnthrottled = (float)diffticksUnthrottled / afsfreq; - - - float error = diffUnthrottled - desiredspf; - - - // reset way-out-of-range values - if (diff > 1) - diff = 1; - if (error > 1 || error < -1) - error = 0; - if (diffUnthrottled > 1) - diffUnthrottled = desiredspf; - - float derivative = (error - lastError) / diff; - lastError = error; - - integral = integral + (error * diff); - integral *= 0.99f; // since our integral isn't reliable, reduce it to 0 over time. - - // "PID controller" constants - // this stuff is probably being done all wrong, but these seem to work ok - const float Kp = 40.0f; - const float Ki = 0.55f; - const float Kd = 0.04f; - - float errorTerm = error * Kp; - float derivativeTerm = derivative * Kd; - float integralTerm = integral * Ki; - float adjustment = errorTerm + derivativeTerm + integralTerm; - - // apply the output adjustment - fSkipFrames += adjustment; - - // if we're running too slowly, prevent the throttle from kicking in - if (adjustment > 0 && fSkipFrames > 0) - ltime -= tfreq / desiredfps; - - preThrottleEndticks = 0; - beginticks = GetCurTime(); - } - - int AutoFrameSkip_GetSkipAmount(int min, int max) - { - int rv = (int)fSkipFrames; - fSkipFramesError += fSkipFrames - rv; - - // resolve accumulated fractional error - // where doing so doesn't push us out of range - while (fSkipFramesError >= 1.0f && rv <= lastSkip && rv < max) - { - fSkipFramesError -= 1.0f; - rv++; - } - while (fSkipFramesError <= -1.0f && rv >= lastSkip && rv > min) - { - fSkipFramesError += 1.0f; - rv--; - } - - // restrict skip amount to requested range - if (rv < min) - rv = min; - if (rv > max) - rv = max; - - // limit maximum error accumulation (it's mainly only for fractional components) - if (fSkipFramesError >= 4.0f) - fSkipFramesError = 4.0f; - if (fSkipFramesError <= -4.0f) - fSkipFramesError = -4.0f; - - // limit ongoing skipframes to requested range + 1 on each side - if (fSkipFrames < min - 1) - fSkipFrames = (float)min - 1; - if (fSkipFrames > max + 1) - fSkipFrames = (float)max + 1; - - // printf("%d", rv); - - lastSkip = rv; - return rv; - } - - - void SpeedThrottle(bool paused) - { - AutoFrameSkip_BeforeThrottle(); - - waiter: - if (signal_unthrottle) - return; - - ulong ttime = GetCurTime(); - - if ((ttime - ltime) < (tfreq / desiredfps)) - { - ulong sleepy = (tfreq / desiredfps) - (ttime - ltime); - sleepy *= 1000; - if (tfreq >= 65536) - sleepy /= afsfreq; - else - sleepy = 0; - if (sleepy >= 10 || paused) - { - Thread.Sleep((int)(sleepy / 2)); - // reduce it further beacuse Sleep usually sleeps for more than the amount we tell it to - } - else if (sleepy > 0) // spin for <1 millisecond waits - { - Thread.Yield(); // limit to other threads on the same CPU core for other short waits - } - goto waiter; - } - if ((ttime - ltime) >= (tfreq * 4 / desiredfps)) - ltime = ttime; - else - ltime += tfreq / desiredfps; - } - } -} diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj index 78279f86ae..2aa1fc873d 100644 --- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj +++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj @@ -347,6 +347,7 @@ + UserControl