use picofe menu, move generic code out of gp2x/
[fceu.git] / drivers / sdl / throttle.c
1 #include <sys/time.h>
2 #include <unistd.h>
3
4 #include "../common/main.h"
5 #include "../common/throttle.h"
6 #include "../common/settings.h"
7
8
9 extern uint8 PAL;
10 extern int FSkip;
11 static int usec_aim = 0, usec_done = 0;
12 static int skip_count = 0;
13
14 void RefreshThrottleFPS(void)
15 {
16         usec_aim = usec_done = skip_count = 0;
17 }
18
19 void SpeedThrottle(void)
20 {
21         static struct timeval tv_prev;
22         struct timeval tv_now;
23         int delta_nom = PAL ? 19997 : 16639; // ~50.007, 19.997 ms/frame : ~60.1, 16.639 ms/frame
24
25
26         if (usec_done == 0) { // first time
27                 usec_done = 1;
28                 gettimeofday(&tv_prev, 0);
29                 return;
30         }
31
32         gettimeofday(&tv_now, 0);
33
34         usec_aim += delta_nom;
35         if (tv_now.tv_sec != tv_prev.tv_sec)
36                 usec_done += 1000000;
37         usec_done += tv_now.tv_usec - tv_prev.tv_usec;
38
39 #ifdef FRAMESKIP
40         if (Settings.frameskip >= 0)
41         {
42                 if (skip_count >= Settings.frameskip)
43                         skip_count = 0;
44                 else {
45                         skip_count++;
46                         FSkip = 1;
47                 }
48         }
49         else if (usec_done > usec_aim + 1024*4)
50         {
51                 /* auto frameskip */
52                 if (usec_done - usec_aim > 1024*32)
53                         usec_done = usec_aim = 1; // too much behind, try to recover..
54                 else
55                         FSkip = 1;
56                 tv_prev = tv_now;
57                 return;
58         }
59 #endif
60
61         tv_prev = tv_now;
62         while (usec_done < usec_aim)
63         {
64                 usleep(300);
65                 gettimeofday(&tv_now, 0);
66
67                 if (tv_now.tv_sec != tv_prev.tv_sec)
68                         usec_done += 1000000;
69                 usec_done += tv_now.tv_usec - tv_prev.tv_usec;
70                 tv_prev = tv_now;
71         }
72         usec_done = usec_done - usec_aim + 1; // reset to prevent overflows
73         usec_aim = 0;
74 }
75