(view as text)
diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp
index e12eb43..452cdfa 100644
--- a/Source/Core/Core/BootManager.cpp
+++ b/Source/Core/Core/BootManager.cpp
@@ -55,7 +55,7 @@ struct ConfigCache
 	unsigned int framelimit;
 	TEXIDevices m_EXIDevice[MAX_EXI_CHANNELS];
 	std::string strBackend, sBackend;
-	bool bSetFramelimit, bSetEXIDevice[MAX_EXI_CHANNELS], bSetUseFPS, bSetVolume, bSetPads[MAX_SI_CHANNELS], bSetWiimoteSource[MAX_BBMOTES];
+	bool bSetFramelimit, bSetEXIDevice[MAX_EXI_CHANNELS], bSetVolume, bSetPads[MAX_SI_CHANNELS], bSetWiimoteSource[MAX_BBMOTES];
 };
 static ConfigCache config_cache;
 
@@ -114,7 +114,6 @@ bool BootCore(const std::string& _rFilename)
 		config_cache.Volume = SConfig::GetInstance().m_Volume;
 		config_cache.sBackend = SConfig::GetInstance().sBackend;
 		config_cache.framelimit = SConfig::GetInstance().m_Framelimit;
-		config_cache.bUseFPS = SConfig::GetInstance().b_UseFPS;
 		for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
 		{
 			config_cache.iWiimoteSource[i] = g_wiimote_sources[i];
@@ -150,8 +149,6 @@ bool BootCore(const std::string& _rFilename)
 		game_ini.Get("Core", "HLE_BS2",				&StartUp.bHLE_BS2, StartUp.bHLE_BS2);
 		if (game_ini.Get("Core", "FrameLimit",		&SConfig::GetInstance().m_Framelimit, SConfig::GetInstance().m_Framelimit))
 			config_cache.bSetFramelimit = true;
-		if (game_ini.Get("Core", "UseFPS",			&SConfig::GetInstance().b_UseFPS, SConfig::GetInstance().b_UseFPS))
-			config_cache.bSetUseFPS = true;
 		if (game_ini.Get("DSP", "Volume",			&SConfig::GetInstance().m_Volume, SConfig::GetInstance().m_Volume))
 			config_cache.bSetVolume = true;
 		game_ini.Get("DSP", "EnableJIT",			&SConfig::GetInstance().m_EnableJIT, SConfig::GetInstance().m_EnableJIT);
@@ -269,8 +266,6 @@ void Stop()
 		// Only change these back if they were actually set by game ini, since they can be changed while a game is running.
 		if (config_cache.bSetFramelimit)
 			SConfig::GetInstance().m_Framelimit = config_cache.framelimit;
-		if (config_cache.bSetUseFPS)
-			SConfig::GetInstance().b_UseFPS = config_cache.bUseFPS;
 		if (config_cache.bSetVolume)
 			SConfig::GetInstance().m_Volume = config_cache.Volume;
 
diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp
index f28dfa5..6bc284c 100644
--- a/Source/Core/Core/ConfigManager.cpp
+++ b/Source/Core/Core/ConfigManager.cpp
@@ -263,7 +263,6 @@ void SConfig::SaveSettings()
 	ini.Set("Core", "RunCompareServer",	m_LocalCoreStartupParameter.bRunCompareServer);
 	ini.Set("Core", "RunCompareClient",	m_LocalCoreStartupParameter.bRunCompareClient);
 	ini.Set("Core", "FrameLimit",		m_Framelimit);
-	ini.Set("Core", "UseFPS",		b_UseFPS);
 
 	// GFX Backend
 	ini.Set("Core", "GFXBackend",	m_LocalCoreStartupParameter.m_strVideoBackend);
@@ -431,7 +430,6 @@ void SConfig::LoadSettings()
 		ini.Get("Core", "FastDiscSpeed",	&m_LocalCoreStartupParameter.bFastDiscSpeed,	false);
 		ini.Get("Core", "DCBZ",				&m_LocalCoreStartupParameter.bDCBZOFF,			false);
 		ini.Get("Core", "FrameLimit",		&m_Framelimit,									1); // auto frame limit by default
-		ini.Get("Core", "UseFPS",			&b_UseFPS,										false); // use vps as default
 
 		// GFX Backend
 		ini.Get("Core", "GFXBackend",  &m_LocalCoreStartupParameter.m_strVideoBackend, "");
diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h
index 6fc411a..7a53647 100644
--- a/Source/Core/Core/ConfigManager.h
+++ b/Source/Core/Core/ConfigManager.h
@@ -51,7 +51,6 @@ struct SConfig : NonCopyable
 	int m_InterfaceLanguage;
 	// framelimit choose
 	unsigned int m_Framelimit;
-	bool b_UseFPS;
 	// other interface settings
 	bool m_InterfaceToolbar;
 	bool m_InterfaceStatusbar;
diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp
index ddbc490..93576e5 100644
--- a/Source/Core/Core/Core.cpp
+++ b/Source/Core/Core/Core.cpp
@@ -613,30 +613,6 @@ bool PauseAndLock(bool doLock, bool unpauseOnUnlock)
 // This should only be called from VI
 void VideoThrottle()
 {
-	u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 2) ?
-		(SConfig::GetInstance().m_Framelimit - 1) * 5 : VideoInterface::TargetRefreshRate;
-
-	if (Host_GetKeyState('\t'))
-		isTabPressed = true;
-	else
-		isTabPressed = false;
-
-	// Disable the frame-limiter when the throttle (Tab) key is held down. Audio throttle: m_Framelimit = 2
-	if (SConfig::GetInstance().m_Framelimit && SConfig::GetInstance().m_Framelimit != 2 && !Host_GetKeyState('\t'))
-	{
-		u32 frametime = ((SConfig::GetInstance().b_UseFPS)? Common::AtomicLoad(DrawnFrame) : DrawnVideo) * 1000 / TargetVPS;
-
-		u32 timeDifference = (u32)Timer.GetTimeDifference();
-		if (timeDifference < frametime)
-		{
-			Common::SleepCurrentThread(frametime - timeDifference - 1);
-		}
-
-		while ((u32)Timer.GetTimeDifference() < frametime)
-			Common::YieldCPU();
-			//Common::SleepCurrentThread(1);
-	}
-
 	// Update info per second
 	u32 ElapseTime = (u32)Timer.GetTimeDifference();
 	if ((ElapseTime >= 1000 && DrawnVideo > 0) || g_requestRefreshInfo)
diff --git a/Source/Core/Core/HW/SystemTimers.cpp b/Source/Core/Core/HW/SystemTimers.cpp
index 976e239..abba38e 100644
--- a/Source/Core/Core/HW/SystemTimers.cpp
+++ b/Source/Core/Core/HW/SystemTimers.cpp
@@ -75,6 +75,7 @@ IPC_HLE_PERIOD: For the Wiimote this is the call schedule:
 #include "Timer.h"
 #include "VideoBackendBase.h"
 #include "CommandProcessor.h"
+#include "Host.h"
 
 
 namespace SystemTimers
@@ -115,6 +116,7 @@ int et_AudioDMA;
 int et_DSP;
 int et_IPC_HLE;
 int et_PatchEngine;	// PatchEngine updates every 1/60th of a second by default
+int et_Throttle;
 
 // These are badly educated guesses
 // Feel free to experiment. Set these in Init below.
@@ -229,6 +231,29 @@ void PatchEngineCallback(u64 userdata, int cyclesLate)
 	CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_PatchEngine);
 }
 
+void ThrottleCallback(u64 last_time, int cyclesLate)
+{
+	u32 time = Common::Timer::GetTimeMs();
+
+	int diff = u32(last_time) - time;
+	bool frame_limiter = SConfig::GetInstance().m_Framelimit && SConfig::GetInstance().m_Framelimit != 2 && !Host_GetKeyState('\t');
+	u32 next_event = GetTicksPerSecond()/1000;
+	if(SConfig::GetInstance().m_Framelimit > 2)
+	{
+		next_event = next_event * (SConfig::GetInstance().m_Framelimit - 1) * 5 / VideoInterface::TargetRefreshRate;
+	}
+
+	const int max_fallback = 40; // 40 ms for one frame on 25 fps games
+	if(frame_limiter && abs(diff) > max_fallback)
+	{
+		WARN_LOG(COMMON, "system too %s, %d ms skipped", diff<0 ? "slow" : "fast", abs(diff) - max_fallback);
+		last_time = time - max_fallback;
+	}
+	else if(frame_limiter && diff > 0)
+		Common::SleepCurrentThread(diff);
+	CoreTiming::ScheduleEvent(next_event - cyclesLate, et_Throttle, last_time + 1);
+}
+
 // split from Init to break a circular dependency between VideoInterface::Init and SystemTimers::Init
 void PreInit()
 {
@@ -274,11 +299,13 @@ void Init()
 	et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
 	et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
 	et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
+	et_Throttle = CoreTiming::RegisterEvent("Throttle", ThrottleCallback);
 
 	CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI);
 	CoreTiming::ScheduleEvent(0, et_DSP);
 	CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI);
 	CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA);
+	CoreTiming::ScheduleEvent(0, et_Throttle, Common::Timer::GetTimeMs());
 	if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU)
 		CoreTiming::ScheduleEvent(CP_PERIOD, et_CP);
 
diff --git a/Source/Core/DolphinWX/ConfigMain.cpp b/Source/Core/DolphinWX/ConfigMain.cpp
index 28e03ae..90525d8 100644
--- a/Source/Core/DolphinWX/ConfigMain.cpp
+++ b/Source/Core/DolphinWX/ConfigMain.cpp
@@ -118,7 +118,6 @@ EVT_CHECKBOX(ID_CPUTHREAD, CConfigMain::CoreSettingsChanged)
 EVT_CHECKBOX(ID_IDLESKIP, CConfigMain::CoreSettingsChanged)
 EVT_CHECKBOX(ID_ENABLECHEATS, CConfigMain::CoreSettingsChanged)
 EVT_CHOICE(ID_FRAMELIMIT, CConfigMain::CoreSettingsChanged)
-EVT_CHECKBOX(ID_FRAMELIMIT_USEFPSFORLIMITING, CConfigMain::CoreSettingsChanged)
 
 EVT_RADIOBOX(ID_CPUENGINE, CConfigMain::CoreSettingsChanged)
 EVT_CHECKBOX(ID_NTSCJ, CConfigMain::CoreSettingsChanged)
@@ -324,7 +323,6 @@ void CConfigMain::InitializeGUIValues()
 	SkipIdle->SetValue(startup_params.bSkipIdle);
 	EnableCheats->SetValue(startup_params.bEnableCheats);
 	Framelimit->SetSelection(SConfig::GetInstance().m_Framelimit);
-	UseFPSForLimiting->SetValue(SConfig::GetInstance().b_UseFPS);
 
 	// General - Advanced
 	for (unsigned int a = 0; a < (sizeof(CPUCores) / sizeof(CPUCore)); ++a)
@@ -549,7 +547,6 @@ void CConfigMain::CreateGUIControls()
 	EnableCheats = new wxCheckBox(GeneralPage, ID_ENABLECHEATS, _("Enable Cheats"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
 	// Framelimit
 	Framelimit = new wxChoice(GeneralPage, ID_FRAMELIMIT, wxDefaultPosition, wxDefaultSize, arrayStringFor_Framelimit, 0, wxDefaultValidator);
-	UseFPSForLimiting = new wxCheckBox(GeneralPage, ID_FRAMELIMIT_USEFPSFORLIMITING, _("Limit by FPS"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
 	// Core Settings - Advanced
 	CPUEngine = new wxRadioBox(GeneralPage, ID_CPUENGINE, _("CPU Emulator Engine"), wxDefaultPosition, wxDefaultSize, arrayStringFor_CPUEngine, 0, wxRA_SPECIFY_ROWS);
 	_NTSCJ = new wxCheckBox(GeneralPage, ID_NTSCJ, _("Force Console as NTSC-J"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
@@ -558,7 +555,6 @@ void CConfigMain::CreateGUIControls()
 	wxBoxSizer* sFramelimit = new wxBoxSizer(wxHORIZONTAL);
 	sFramelimit->Add(TEXT_BOX(GeneralPage, _("Framelimit:")), 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM, 5);
 	sFramelimit->Add(Framelimit, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
-	sFramelimit->Add(UseFPSForLimiting, 0, wxALL | wxEXPAND, 5);
 	wxStaticBoxSizer* const sbBasic = new wxStaticBoxSizer(wxVERTICAL, GeneralPage, _("Basic Settings"));
 	sbBasic->Add(CPUThread, 0, wxALL, 5);
 	sbBasic->Add(SkipIdle, 0, wxALL, 5);
@@ -890,9 +886,6 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event)
 		SConfig::GetInstance().m_Framelimit = Framelimit->GetSelection();
 		AudioCommon::UpdateSoundStream();
 		break;
-	case ID_FRAMELIMIT_USEFPSFORLIMITING:
-		SConfig::GetInstance().b_UseFPS = UseFPSForLimiting->IsChecked();
-		break;
 	// Core - Advanced
 	case ID_CPUENGINE:
 		SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore = CPUCores[CPUEngine->GetSelection()].CPUid;
diff --git a/Source/Core/DolphinWX/ConfigMain.h b/Source/Core/DolphinWX/ConfigMain.h
index 43fa90c..b2f30b1 100644
--- a/Source/Core/DolphinWX/ConfigMain.h
+++ b/Source/Core/DolphinWX/ConfigMain.h
@@ -53,7 +53,6 @@ private:
 		ID_IDLESKIP,
 		ID_ENABLECHEATS,
 		ID_FRAMELIMIT,
-		ID_FRAMELIMIT_USEFPSFORLIMITING,
 
 		ID_CPUENGINE,
 		ID_DSPTHREAD,
@@ -123,7 +122,6 @@ private:
 	wxCheckBox* SkipIdle;
 	wxCheckBox* EnableCheats;
 	wxChoice* Framelimit;
-	wxCheckBox* UseFPSForLimiting;
 
 	// Advanced
 	wxRadioBox* CPUEngine;