use picofe menu, move generic code out of gp2x/
[fceu.git] / drivers / gp2x / throttle.c
index 81cd916..5a5f55e 100644 (file)
 #include <sys/time.h>
+#include "../common/settings.h"
 #include "main.h"
+#include "minimal.h"
 #include "throttle.h"
 
-#if 0
-static uint64 tfreq;
-static uint64 desiredfps;
 
-void RefreshThrottleFPS(void)
-{
- uint64 f=FCEUI_GetDesiredFPS();
- // great, a bit faster than before
- //f = (f*65) >> 6;
- desiredfps=f>>8;
- tfreq=1000000;
- tfreq<<=16;    /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */
-}
+extern uint8 PAL;
+extern int FSkip;
+static int skip_count = 0;
+static struct timeval tv_prev;
 
-static uint64 GetCurTime(void)
-{
- uint64 ret;
- struct timeval tv;
+#define tvdiff(tv1, tv2) \
+       ((tv1.tv_sec - tv2.tv_sec) * 1000000 + tv1.tv_usec - tv2.tv_usec)
 
- gettimeofday(&tv,0);
- ret=(uint64)tv.tv_sec*1000000;
- ret+=tv.tv_usec;
- return(ret);
+#define tvadd(tv, usec) { \
+       tv.tv_usec += usec; \
+       if (tv.tv_usec >= 1000000) { \
+               tv.tv_sec += 1; \
+               tv.tv_usec -= 1000000; \
+       } \
 }
 
-INLINE void SpeedThrottle(void)
-{
- static uint64 ttime,ltime;
-
- waiter:
-
- ttime=GetCurTime();
-
- if( (ttime-ltime) < (tfreq/desiredfps) )
- {
-  goto waiter;
- }
- if( (ttime-ltime) >= (tfreq*4/desiredfps))
-  ltime=ttime;
- else
-  ltime+=tfreq/desiredfps;
+#define tvsub(tv, usec) { \
+       tv.tv_usec -= usec; \
+       if (tv.tv_usec < 0) { \
+               tv.tv_sec -= 1; \
+               tv.tv_usec += 1000000; \
+       } \
 }
 
-#else
-
-extern uint8 PAL;
-extern int FSkip, FSkip_setting;
-static int usec_aim = 0, usec_done = 0;
-static int skip_count = 0;
+void RefreshThrottleFPS(void)
+{
+       skip_count = 0;
+       if (Settings.perfect_vsync)
+       {
+               gp2x_video_wait_vsync();
+       }
+       gettimeofday(&tv_prev, 0);
+       tvsub(tv_prev, PAL ? 19997 : 16639);
+}
 
-INLINE void SpeedThrottle(void)
+static void wait_to(struct timeval *tv_aim)
 {
-       static struct timeval tv_prev;
        struct timeval tv_now;
-       int delta_nom = PAL ? 19997 : 16639; // ~50.007, 19.997 ms/frame : ~60.1, 16.639 ms/frame
-
+       int diff;
 
-       if (usec_done == 0) { // first time
-               usec_done = 1;
-               gettimeofday(&tv_prev, 0);
-               return;
+       do
+       {
+               gettimeofday(&tv_now, 0);
+               diff = tvdiff((*tv_aim), tv_now);
        }
+       while (diff > 0);
+}
 
-       gettimeofday(&tv_now, 0);
+#include <stdio.h>
+void SpeedThrottle(void)
+{
+       struct timeval tv_now, tv_aim;
+       int frame_time = PAL ? 19997 : 16639; // ~50.007, 19.997 ms/frame : ~60.1, 16.639 ms/frame
+       int tdiff;
+
+       tv_aim = tv_prev;
+       tvadd(tv_aim, frame_time);
 
-       usec_aim += delta_nom;
-       if (tv_now.tv_sec != tv_prev.tv_sec)
-               usec_done += 1000000;
-       usec_done += tv_now.tv_usec - tv_prev.tv_usec;
+       gettimeofday(&tv_now, 0);
+       tdiff = tvdiff(tv_now, tv_aim);
 
 #ifdef FRAMESKIP
-       if (FSkip_setting >= 0)
+       if (Settings.frameskip >= 0)
        {
-               if (skip_count >= FSkip_setting)
+               if (skip_count >= Settings.frameskip)
                        skip_count = 0;
                else {
                        skip_count++;
                        FSkip = 1;
                }
        }
-       else if (usec_done > usec_aim)
+       else if (tdiff >= frame_time)
        {
                /* auto frameskip */
-               if (usec_done - usec_aim > 150000)
-                       usec_done = usec_aim = 0; // too much behind, try to recover..
-               FSkip = 1;
-               tv_prev = tv_now;
+               if (/*tdiff < 36*1024 &&*/ skip_count < 6) {    // limit frameskip
+                       FSkip = 1;
+                       skip_count++;
+               } else
+                       skip_count = 0;
+
+               if (tdiff < 92*1024)
+                       tv_prev = tv_aim;
+               else
+                       tv_prev = tv_now; // something went wrong, try to recover
                return;
        }
+       else
+               skip_count = 0;
 #endif
 
-       tv_prev = tv_now;
-       while (usec_done < usec_aim)
+       /* throttle */
+       if (tdiff < 0)
        {
-               gettimeofday(&tv_now, 0);
-
-               if (tv_now.tv_sec != tv_prev.tv_sec)
-                       usec_done += 1000000;
-               usec_done += tv_now.tv_usec - tv_prev.tv_usec;
-               tv_prev = tv_now;
+               if (Settings.perfect_vsync)
+               {
+                       if (tdiff <= (PAL ? 19997/2 : 16639/2))
+                       {
+                               struct timeval tv_tmp = tv_aim;
+                               tvsub(tv_tmp, 5000);
+                               wait_to(&tv_tmp);
+                       }
+                       gp2x_video_wait_vsync();
+                       gettimeofday(&tv_prev, 0);
+                       return;
+               }
+               else
+               {
+                       wait_to(&tv_aim);
+               }
        }
-       usec_done = usec_done - usec_aim + 1; // reset to prevent overflows
-       usec_aim = 0;
+
+       tv_prev = tv_aim;
 }
-#endif