Make joysticks actually work
[lsnes.git] / framerate.cpp
blob3d44638a158b14ef42df1981b6db487a6f5f2ca9
1 #include "framerate.hpp"
2 #include "settings.hpp"
3 #include <string>
4 #include <sstream>
5 #include <iostream>
6 #include <stdexcept>
8 namespace
10 double nominal_rate = 60;
11 double fps_value = 0;
12 const double exp_factor = 0.97;
13 uint64_t last_frame_msec = 0;
14 bool last_frame_msec_valid = false;
15 bool target_nominal = true;
16 double target_fps = 60;
17 bool target_infinite = false;
18 uint64_t wait_duration = 0;
20 struct setting_targetfps : public setting
22 setting_targetfps() throw(std::bad_alloc)
23 : setting("targetfps")
27 void blank() throw(std::bad_alloc, std::runtime_error)
29 target_nominal = true;
30 target_infinite = false;
31 target_fps = nominal_rate;
34 bool is_set() throw()
36 return !target_nominal;
39 virtual void set(const std::string& value) throw(std::bad_alloc, std::runtime_error)
41 double tmp;
42 const char* s;
43 char* e;
44 if(value == "infinite") {
45 target_infinite = true;
46 target_nominal = false;
47 return;
49 s = value.c_str();
50 tmp = strtod(s, &e);
51 if(*e)
52 throw std::runtime_error("Invalid frame rate");
53 if(tmp < 0.001)
54 throw std::runtime_error("Target frame rate must be at least 0.001fps");
55 target_fps = tmp;
56 target_infinite = false;
57 target_nominal = false;
60 virtual std::string get() throw(std::bad_alloc)
62 if(target_nominal)
63 return "";
64 else {
65 std::ostringstream o;
66 o << target_fps;
67 return o.str();
71 } targetfps;
74 void set_nominal_framerate(double fps) throw()
76 nominal_rate = fps;
77 if(target_nominal) {
78 target_fps = nominal_rate;
79 target_infinite = false;
83 double get_framerate() throw()
85 return fps_value;
88 void ack_frame_tick(uint64_t msec) throw()
90 if(!last_frame_msec_valid) {
91 last_frame_msec = msec;
92 last_frame_msec_valid = true;
93 return;
95 uint64_t frame_msec = msec - last_frame_msec;
96 fps_value = exp_factor * fps_value + (1 - exp_factor) * (1000.0 / frame_msec);
97 last_frame_msec = msec;
100 uint64_t to_wait_frame(uint64_t msec) throw()
102 //Very simple algorithm. TODO: Make better one.
103 if(!last_frame_msec_valid || target_infinite)
104 return 0;
105 if(get_framerate() < target_fps && wait_duration > 0)
106 wait_duration--;
107 else if(get_framerate() > target_fps)
108 wait_duration++;
109 return wait_duration;