1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 
5 // FIXME: REMOVE
6 #include "../emu/video.h"
7 #ifdef WINDOWS
8 //#define _WIN32_WINNT 0x0501
9 #include <Windows.h>
10 #endif
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <fs/base.h>
16 #include <fs/glib.h>
17 #include <fs/log.h>
18 #include <fs/ml.h>
19 #include <fs/thread.h>
20 
21 #if 0
22 #include <sched.h>
23 #include <errno.h>
24 #include <sys/time.h>
25 #include <sys/resource.h>
26 #endif
27 
28 #include "ml_internal.h"
29 
30 int g_fs_ml_benchmarking = 0;
31 
32 int g_fs_ml_video_width = 0;
33 int g_fs_ml_video_height = 0;
34 int g_fs_ml_video_sync = 0;
35 int g_fs_ml_video_sync_low_latency = 0;
36 int g_fs_ml_vblank_sync = 0;
37 
38 int g_fs_ml_target_frame_time = 0;
39 
40 // when OpenGL is reinitialized, we update this version (because we may need
41 // to reload textures, etc)
42 int g_fs_ml_opengl_context_stamp = 0;
43 
44 fs_ml_int_function g_fs_ml_video_update_function = NULL;
45 fs_ml_void_function g_fs_ml_video_render_function = NULL;
46 fs_ml_void_function g_fs_ml_video_post_render_function = NULL;
47 
48 //fs_ml_input_device *g_fs_ml_input_devices = NULL;
49 fs_ml_input_device *g_fs_ml_input_devices = NULL;
50 int g_fs_ml_input_device_count = 0;
51 
52 static int g_quit;
53 static fs_ml_void_function g_quit_function = NULL;
54 
55 fs_mutex *g_fs_ml_video_screenshot_mutex = NULL;
56 //int g_fs_ml_video_screenshot = 0;
57 //char *g_fs_ml_video_screenshots_dir = NULL;
58 //char *g_fs_ml_video_screenshots_prefix = NULL;
59 char *g_fs_ml_video_screenshot_path = NULL;
60 
fs_ml_set_quit_function(fs_ml_void_function function)61 void fs_ml_set_quit_function(fs_ml_void_function function) {
62     g_quit_function = function;
63 }
64 
fs_ml_video_screenshot(const char * path)65 void fs_ml_video_screenshot(const char *path) {
66     fs_mutex_lock(g_fs_ml_video_screenshot_mutex);
67     if (g_fs_ml_video_screenshot_path) {
68         g_free(g_fs_ml_video_screenshot_path);
69     }
70     g_fs_ml_video_screenshot_path = g_strdup(path);
71 #if 0
72     if (g_fs_ml_video_screenshots_dir) {
73         g_free(g_fs_ml_video_screenshots_dir);
74     }
75     if (g_fs_ml_video_screenshots_prefix) {
76         g_free(g_fs_ml_video_screenshots_prefix);
77     }
78     g_fs_ml_video_screenshots_dir = g_strdup(screenshots_dir);
79     g_fs_ml_video_screenshots_prefix = g_strdup(prefix);
80     g_fs_ml_video_screenshot = number;
81 #endif
82     fs_mutex_unlock(g_fs_ml_video_screenshot_mutex);
83 }
84 
fs_ml_maybe_quit()85 void fs_ml_maybe_quit() {
86     fs_log("fs_ml_maybe_quit\n");
87     // Breaking the abstraction here due to lazyness
88     fs_emu_quit();
89 }
90 
fs_ml_quit()91 void fs_ml_quit() {
92     fs_log("fs_ml_quit\n");
93     if (g_quit) {
94         fs_log("fs_ml_quit already called\n");
95         return;
96     }
97     if (g_quit_function) {
98         fs_log("running g_quit_function\n");
99         g_quit_function();
100     }
101     g_quit = 1;
102 }
103 
fs_ml_is_quitting()104 int fs_ml_is_quitting() {
105     return g_quit;
106 }
107 
fs_ml_input_device_count()108 int fs_ml_input_device_count() {
109     //return g_fs_ml_input_device_count;
110     return FS_ML_INPUT_DEVICES_MAX;
111 }
112 
fs_ml_get_input_devices(int * count)113 fs_ml_input_device *fs_ml_get_input_devices(int* count) {
114     if (count) {
115         *count = g_fs_ml_input_device_count;
116     }
117     return g_fs_ml_input_devices;
118 }
119 
fs_ml_input_device_get(int index,fs_ml_input_device * device)120 int fs_ml_input_device_get(int index, fs_ml_input_device *device)
121 {
122     if (index < 0) {
123         return 0;
124     }
125     if (index >= FS_ML_INPUT_DEVICES_MAX) {
126     //if (index >= g_fs_ml_input_device_count) {
127         return 0;
128     }
129     if (device == NULL) {
130         return 0;
131     }
132     if (g_fs_ml_input_devices[index].name == NULL) {
133         return 0;
134     }
135     *device = g_fs_ml_input_devices[index];
136     return 1;
137 }
138 
fs_ml_get_vblank_sync()139 int fs_ml_get_vblank_sync() {
140     return g_fs_ml_vblank_sync;
141 }
142 
fs_ml_get_video_sync()143 int fs_ml_get_video_sync() {
144     return g_fs_ml_video_sync;
145 }
fs_ml_video_sync_enable(int enable)146 void fs_ml_video_sync_enable(int enable) {
147     fs_log("fs_ml_video_sync_enable(%d)\n", enable);
148     g_fs_ml_video_sync = enable;
149 }
150 
fs_ml_vblank_sync_enable()151 void fs_ml_vblank_sync_enable() {
152     g_fs_ml_vblank_sync = 1;
153 }
154 
fs_ml_video_width()155 int fs_ml_video_width() {
156     return g_fs_ml_video_width;
157 }
158 
fs_ml_video_height()159 int fs_ml_video_height() {
160     return g_fs_ml_video_height;
161 }
162 
fs_ml_video_set_update_function(fs_ml_int_function function)163 void fs_ml_video_set_update_function(fs_ml_int_function function)
164 {
165     g_fs_ml_video_update_function = function;
166 }
167 
fs_ml_video_set_render_function(fs_ml_void_function function)168 void fs_ml_video_set_render_function(fs_ml_void_function function)
169 {
170     g_fs_ml_video_render_function = function;
171 }
172 
fs_ml_video_set_post_render_function(fs_ml_void_function function)173 void fs_ml_video_set_post_render_function(fs_ml_void_function function)
174 {
175     g_fs_ml_video_post_render_function = function;
176 }
177 
fs_ml_init(void)178 void fs_ml_init(void)
179 {
180     fs_log("fs_ml_init (operating system: %s)\n", OS_NAME);
181 
182     g_fs_ml_video_render_function = NULL;
183     g_fs_ml_video_post_render_function = NULL;
184 
185 #ifdef WINDOWS
186 #ifndef TIMERR_NOERROR
187 #define TIMERR_NOERROR 0
188 #endif
189     if (timeBeginPeriod(1) == TIMERR_NOERROR) {
190         fs_log("successfully set timeBeginPeriod(1)\n");
191     } else {
192         fs_log("error setting timeBeginPeriod(1)\n");
193     }
194     if (SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS)) {
195         fs_log("set process priority class to ABOVE_NORMAL_PRIORITY_CLASS\n");
196     } else {
197         int dwError = GetLastError();
198         fs_log("Failed to set process priority class (%d)\n", dwError);
199     }
200 #endif
201 
202 #if 0
203     struct rlimit rlim;
204     getrlimit(RLIMIT_RTPRIO, &rlim);
205     printf("%d %d\n", rlim.rlim_cur, rlim.rlim_max);
206     //rlim.rlim_cur = 10;
207     //rlim.rlim_max = 10;
208     //setrlimit(RLIMIT_RTPRIO, &rlim);
209     //getrlimit(RLIMIT_RTPRIO, &rlim);
210     //printf("%d %d\n", rlim.rlim_cur, rlim.rlim_max);
211 
212     struct sched_param params;
213     //params.sched_priority = sched_get_priority_min(SCHED_FIFO);
214     params.sched_priority = 50;
215     fs_log("trying to set priority to %d\n", params.sched_priority);
216     int result = sched_setscheduler(0, SCHED_FIFO, &params);
217     if (result == 0) {
218         fs_log("has set real time priority\n");
219     }
220     else {
221         fs_log("could not set real time priority, errno = %d\n", errno);
222     }
223 #endif
224 }
225 
fs_ml_init_2(void)226 void fs_ml_init_2(void)
227 {
228     fs_ml_input_init();
229 
230     g_fs_ml_video_screenshot_mutex = fs_mutex_create();
231 }
232 
fs_ml_get_refresh_rate(void)233 double fs_ml_get_refresh_rate(void)
234 {
235     return g_fs_emu_video_frame_rate_host;
236 }
237