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, ¶ms);
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