diff --git a/src/screen.c b/src/screen.c
index 73af4313deab86ec5bdf4418f8428d6b035a4e70..f81a6563d6a19833f867917ab29142730ad7c714 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -451,18 +451,50 @@ boolean SCR_IsAspectCorrect(INT32 width, INT32 height)
 // moved out of os-specific code for consistency
 static boolean fpsgraph[TICRATE];
 static tic_t lasttic;
+static tic_t totaltics;
 
-void SCR_DisplayTicRate(void)
+static UINT32 fpstime = 0;
+static UINT32 lastupdatetime = 0;
+
+#define FPSUPDATERATE 1/20 // What fraction of a second to update at. The fraction will not simplify to 0, trust me.
+#define FPSMAXSAMPLES 16
+
+static UINT32 fpssamples[FPSMAXSAMPLES];
+static UINT32 fpssampleslen = 0;
+static UINT32 fpssum = 0;
+double aproxfps = 0.0f;
+
+void SCR_CalcAproxFps(void)
 {
-	tic_t i;
+	tic_t i = 0;
 	tic_t ontic = I_GetTime();
-	tic_t totaltics = 0;
-	INT32 ticcntcolor = 0;
-	const INT32 h = vid.height-(8*vid.dupy);
 
-	if (gamestate == GS_NULL)
-		return;
+	totaltics = 0;
+
+	// Update FPS time
+	if (I_PreciseToMicros(fpstime - lastupdatetime) > 1000000 * FPSUPDATERATE)
+	{
+		if (fpssampleslen == FPSMAXSAMPLES)
+		{
+			fpssum -= fpssamples[0];
+
+			for (i = 1; i < fpssampleslen; i++)
+				fpssamples[i-1] = fpssamples[i];
+		}
+		else
+			fpssampleslen++;
+
+		fpssamples[fpssampleslen-1] = I_GetPreciseTime() - fpstime;
+		fpssum += fpssamples[fpssampleslen-1];
+
+		aproxfps = 1000000 / (I_PreciseToMicros(fpssum) / (double)fpssampleslen);
 
+		lastupdatetime = I_GetPreciseTime();
+	}
+
+	fpstime = I_GetPreciseTime();
+
+	// Update ticrate time
 	for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i)
 		fpsgraph[i % TICRATE] = false;
 
@@ -472,21 +504,30 @@ void SCR_DisplayTicRate(void)
 		if (fpsgraph[i])
 			++totaltics;
 
+	lasttic = ontic;
+}
+
+void SCR_DisplayTicRate(void)
+{
+	INT32 ticcntcolor = 0;
+	const INT32 h = vid.height-(8*vid.dupy);
+
+	if (gamestate == GS_NULL)
+		return;
+
 	if (totaltics <= TICRATE/2) ticcntcolor = V_REDMAP;
 	else if (totaltics == TICRATE) ticcntcolor = V_GREENMAP;
 
 	if (cv_ticrate.value == 2) // compact counter
-		V_DrawString(vid.width-(16*vid.dupx), h,
-			ticcntcolor|V_NOSCALESTART|V_USERHUDTRANS, va("%02d", totaltics));
+		V_DrawString(vid.width-(24*vid.dupx), h,
+			ticcntcolor|V_NOSCALESTART|V_USERHUDTRANS, va("%03.0f", aproxfps));
 	else if (cv_ticrate.value == 1) // full counter
 	{
-		V_DrawString(vid.width-(72*vid.dupx), h,
+		V_DrawString(vid.width-(88*vid.dupx), h,
 			V_YELLOWMAP|V_NOSCALESTART|V_USERHUDTRANS, "FPS:");
-		V_DrawString(vid.width-(40*vid.dupx), h,
-			ticcntcolor|V_NOSCALESTART|V_USERHUDTRANS, va("%02d/%02u", totaltics, TICRATE));
+		V_DrawString(vid.width-(56*vid.dupx), h,
+			ticcntcolor|V_NOSCALESTART|V_USERHUDTRANS, va("%03.0f/%03u", aproxfps, TICRATE));
 	}
-
-	lasttic = ontic;
 }
 
 void SCR_DisplayLocalPing(void)
diff --git a/src/screen.h b/src/screen.h
index 37695316916ad839be0e8211a8531e8addf0180d..425d10954a525fa39cdfcf687708d881b4900e60 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -181,6 +181,7 @@ extern boolean R_SSE2;
 extern viddef_t vid;
 extern INT32 setmodeneeded; // mode number to set if needed, or 0
 extern UINT8 setrenderneeded;
+extern double aproxfps;
 
 void SCR_ChangeRenderer(void);
 
@@ -211,6 +212,8 @@ void SCR_CheckDefaultMode(void);
 // Set the mode number which is saved in the config
 void SCR_SetDefaultMode(void);
 
+void SCR_CalcAproxFps(void);
+
 FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height);
 
 // move out to main code for consistency
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index a27a5ebd2687b9e7c6dee529e3a40aa9c76f54e1..f90eb09aee435845fe6455cd2a59a107894a9188 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1178,12 +1178,11 @@ void I_UpdateNoBlit(void)
 // from PrBoom's src/SDL/i_video.c
 static inline boolean I_SkipFrame(void)
 {
-#if 0
+#if 1
+	return false;
+#else
 	static boolean skip = false;
 
-	if (rendermode != render_soft)
-		return false;
-
 	skip = !skip;
 
 	switch (gamestate)
@@ -1199,7 +1198,6 @@ static inline boolean I_SkipFrame(void)
 			return false;
 	}
 #endif
-	return false;
 }
 
 //
@@ -1210,6 +1208,8 @@ void I_FinishUpdate(void)
 	if (rendermode == render_none)
 		return; //Alam: No software or OpenGl surface
 
+	SCR_CalcAproxFps();
+
 	if (I_SkipFrame())
 		return;