7badc935 |
1 | /* |
2 | * (C) GraÅžvydas "notaz" Ignotas, 2011,2012 |
3 | * |
4 | * This work is licensed under the terms of any of these licenses |
5 | * (at your option): |
6 | * - GNU GPL, version 2 or later. |
7 | * - GNU LGPL, version 2.1 or later. |
8 | * See the COPYING file in the top-level directory. |
9 | */ |
10 | |
11 | #include <stdio.h> |
12 | #include <SDL.h> |
cc56203b |
13 | |
14 | #include "libpicofe/input.h" |
15 | #include "libpicofe/in_sdl.h" |
16 | #include "libpicofe/menu.h" |
b07c18e8 |
17 | #include "plugin_lib.h" |
18 | #include "main.h" |
a8376201 |
19 | #include "menu.h" |
7badc935 |
20 | #include "plat.h" |
21 | #include "revision.h" |
22 | |
b07c18e8 |
23 | static const struct in_default_bind in_sdl_defbinds[] = { |
2e6189bc |
24 | { SDLK_UP, IN_BINDTYPE_PLAYER12, DKEY_UP }, |
25 | { SDLK_DOWN, IN_BINDTYPE_PLAYER12, DKEY_DOWN }, |
26 | { SDLK_LEFT, IN_BINDTYPE_PLAYER12, DKEY_LEFT }, |
27 | { SDLK_RIGHT, IN_BINDTYPE_PLAYER12, DKEY_RIGHT }, |
28 | { SDLK_d, IN_BINDTYPE_PLAYER12, DKEY_TRIANGLE }, |
29 | { SDLK_z, IN_BINDTYPE_PLAYER12, DKEY_CROSS }, |
30 | { SDLK_x, IN_BINDTYPE_PLAYER12, DKEY_CIRCLE }, |
31 | { SDLK_s, IN_BINDTYPE_PLAYER12, DKEY_SQUARE }, |
32 | { SDLK_v, IN_BINDTYPE_PLAYER12, DKEY_START }, |
33 | { SDLK_c, IN_BINDTYPE_PLAYER12, DKEY_SELECT }, |
34 | { SDLK_w, IN_BINDTYPE_PLAYER12, DKEY_L1 }, |
35 | { SDLK_r, IN_BINDTYPE_PLAYER12, DKEY_R1 }, |
36 | { SDLK_e, IN_BINDTYPE_PLAYER12, DKEY_L2 }, |
37 | { SDLK_t, IN_BINDTYPE_PLAYER12, DKEY_R2 }, |
38 | { SDLK_ESCAPE, IN_BINDTYPE_EMU, SACTION_ENTER_MENU }, |
456f1b86 |
39 | { SDLK_F1, IN_BINDTYPE_EMU, SACTION_SAVE_STATE }, |
40 | { SDLK_F2, IN_BINDTYPE_EMU, SACTION_LOAD_STATE }, |
41 | { SDLK_F3, IN_BINDTYPE_EMU, SACTION_PREV_SSLOT }, |
42 | { SDLK_F4, IN_BINDTYPE_EMU, SACTION_NEXT_SSLOT }, |
43 | { SDLK_F5, IN_BINDTYPE_EMU, SACTION_TOGGLE_FSKIP }, |
44 | { SDLK_F6, IN_BINDTYPE_EMU, SACTION_SCREENSHOT }, |
dde7da71 |
45 | { SDLK_F7, IN_BINDTYPE_EMU, SACTION_TOGGLE_FPS }, |
456f1b86 |
46 | { SDLK_F8, IN_BINDTYPE_EMU, SACTION_SWITCH_DISPMODE }, |
a8376201 |
47 | { SDLK_F11, IN_BINDTYPE_EMU, SACTION_TOGGLE_FULLSCREEN }, |
dde7da71 |
48 | { SDLK_BACKSPACE, IN_BINDTYPE_EMU, SACTION_FAST_FORWARD }, |
2e6189bc |
49 | { 0, 0, 0 } |
7badc935 |
50 | }; |
51 | |
a8376201 |
52 | // XXX: maybe determine this instead.. |
53 | #define WM_DECORATION_H 32 |
54 | |
7badc935 |
55 | static SDL_Surface *screen; |
a8376201 |
56 | static SDL_Overlay *overlay; |
57 | static int window_w, window_h; |
58 | static int fs_w, fs_h; |
59 | static int psx_w, psx_h; |
2e6189bc |
60 | static void *menubg_img; |
a8376201 |
61 | static int in_menu, pending_resize, old_fullscreen; |
7badc935 |
62 | |
63 | static int change_video_mode(int w, int h) |
64 | { |
a8376201 |
65 | psx_w = w; |
66 | psx_h = h; |
67 | |
68 | if (overlay != NULL) { |
69 | SDL_FreeYUVOverlay(overlay); |
70 | overlay = NULL; |
71 | } |
72 | |
73 | if (g_use_overlay && !in_menu) { |
74 | Uint32 flags = SDL_RESIZABLE; |
75 | int win_w = window_w; |
76 | int win_h = window_h; |
77 | |
78 | if (g_fullscreen) { |
79 | flags |= SDL_FULLSCREEN; |
80 | win_w = fs_w; |
81 | win_h = fs_h; |
82 | } |
83 | |
84 | screen = SDL_SetVideoMode(win_w, win_h, 0, flags); |
85 | if (screen == NULL) { |
86 | fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); |
87 | return -1; |
88 | } |
89 | |
90 | overlay = SDL_CreateYUVOverlay(w, h, SDL_UYVY_OVERLAY, screen); |
91 | if (overlay != NULL) { |
92 | /*printf("overlay: fmt %x, planes: %d, pitch: %d, hw: %d\n", |
93 | overlay->format, overlay->planes, *overlay->pitches, |
94 | overlay->hw_overlay);*/ |
95 | |
96 | if ((long)overlay->pixels[0] & 3) |
97 | fprintf(stderr, "warning: overlay pointer is unaligned\n"); |
98 | if (!overlay->hw_overlay) |
99 | fprintf(stderr, "warning: video overlay is not hardware accelerated," |
100 | " you may want to disable it.\n"); |
101 | } |
102 | else { |
103 | fprintf(stderr, "warning: could not create overlay.\n"); |
104 | } |
7badc935 |
105 | } |
106 | |
a8376201 |
107 | if (overlay == NULL) { |
108 | screen = SDL_SetVideoMode(w, h, 16, 0); |
109 | if (screen == NULL) { |
110 | fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); |
111 | return -1; |
112 | } |
113 | |
114 | if (!in_menu) { |
115 | window_w = screen->w; |
116 | window_h = screen->h; |
117 | } |
118 | } |
119 | |
120 | old_fullscreen = g_fullscreen; |
7badc935 |
121 | return 0; |
122 | } |
123 | |
a8376201 |
124 | static void event_handler(void *event_) |
125 | { |
126 | SDL_Event *event = event_; |
127 | |
128 | if (event->type == SDL_VIDEORESIZE) { |
129 | //printf("%dx%d\n", event->resize.w, event->resize.h); |
130 | if (overlay != NULL && !g_fullscreen && !old_fullscreen) { |
131 | window_w = event->resize.w; |
132 | window_h = event->resize.h; |
133 | pending_resize = 1; |
134 | } |
135 | } |
136 | } |
137 | |
7badc935 |
138 | void plat_init(void) |
139 | { |
a8376201 |
140 | const SDL_VideoInfo *info; |
141 | int ret, h; |
7badc935 |
142 | |
143 | ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); |
144 | if (ret != 0) { |
145 | fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); |
146 | exit(1); |
147 | } |
148 | |
a8376201 |
149 | info = SDL_GetVideoInfo(); |
150 | if (info != NULL) { |
151 | fs_w = info->current_w; |
152 | fs_h = info->current_h; |
153 | } |
154 | |
155 | in_menu = 1; |
7badc935 |
156 | g_menuscreen_w = 640; |
a8376201 |
157 | if (fs_w != 0 && g_menuscreen_w > fs_w) |
158 | g_menuscreen_w = fs_w; |
7badc935 |
159 | g_menuscreen_h = 480; |
a8376201 |
160 | if (fs_h != 0) { |
161 | h = fs_h; |
162 | if (info && info->wm_available && h > WM_DECORATION_H) |
163 | h -= WM_DECORATION_H; |
164 | if (g_menuscreen_h > h) |
165 | g_menuscreen_h = h; |
166 | } |
167 | |
7badc935 |
168 | ret = change_video_mode(g_menuscreen_w, g_menuscreen_h); |
169 | if (ret != 0) { |
170 | ret = change_video_mode(0, 0); |
171 | if (ret != 0) |
172 | goto fail; |
173 | |
174 | if (screen->w < 320 || screen->h < 240) { |
175 | fprintf(stderr, "resolution %dx%d is too small, sorry.\n", |
176 | screen->w, screen->h); |
177 | goto fail; |
178 | } |
7badc935 |
179 | } |
a8376201 |
180 | g_menuscreen_w = window_w = screen->w; |
181 | g_menuscreen_h = window_h = screen->h; |
182 | |
7badc935 |
183 | SDL_WM_SetCaption("PCSX-ReARMed " REV, NULL); |
184 | |
2e6189bc |
185 | menubg_img = malloc(640 * 512 * 2); |
186 | if (menubg_img == NULL) |
187 | goto fail; |
188 | |
a8376201 |
189 | in_sdl_init(in_sdl_defbinds, event_handler); |
7badc935 |
190 | in_probe(); |
4ea7de6a |
191 | pl_rearmed_cbs.only_16bpp = 1; |
7badc935 |
192 | return; |
193 | |
194 | fail: |
195 | SDL_Quit(); |
196 | exit(1); |
197 | } |
198 | |
199 | void plat_finish(void) |
200 | { |
2e6189bc |
201 | free(menubg_img); |
202 | menubg_img = NULL; |
7badc935 |
203 | SDL_Quit(); |
204 | } |
205 | |
ab423939 |
206 | void plat_gvideo_open(int is_pal) |
7badc935 |
207 | { |
208 | } |
209 | |
210 | void *plat_gvideo_set_mode(int *w, int *h, int *bpp) |
211 | { |
212 | change_video_mode(*w, *h); |
213 | return screen->pixels; |
214 | } |
215 | |
a8376201 |
216 | static void test_convert(void *d, const void *s, int pixels) |
217 | { |
218 | unsigned int *dst = d; |
219 | const unsigned short *src = s; |
220 | int r0, g0, b0, r1, g1, b1; |
221 | int y0, y1, u, v; |
222 | |
223 | for (; pixels > 0; src += 2, dst++, pixels -= 2) { |
224 | r0 = src[0] >> 11; |
225 | g0 = (src[0] >> 6) & 0x1f; |
226 | b0 = src[0] & 0x1f; |
227 | r1 = src[1] >> 11; |
228 | g1 = (src[1] >> 6) & 0x1f; |
229 | b1 = src[1] & 0x1f; |
230 | y0 = (int)((0.299f * r0) + (0.587f * g0) + (0.114f * b0)); |
231 | y1 = (int)((0.299f * r1) + (0.587f * g1) + (0.114f * b1)); |
232 | //u = (int)(((-0.169f * r0) + (-0.331f * g0) + ( 0.499f * b0)) * 8) + 128; |
233 | //v = (int)((( 0.499f * r0) + (-0.418f * g0) + (-0.0813f * b0)) * 8) + 128; |
234 | u = (int)(8 * 0.565f * (b0 - y0)) + 128; |
235 | v = (int)(8 * 0.713f * (r0 - y0)) + 128; |
236 | // valid Y range seems to be 16..235 |
237 | y0 = 16 + 219 * y0 / 31; |
238 | y1 = 16 + 219 * y1 / 31; |
239 | |
240 | if (y0 < 0 || y0 > 255 || y1 < 0 || y1 > 255 |
241 | || u < 0 || u > 255 || v < 0 || v > 255) |
242 | { |
243 | printf("oor: %d, %d, %d, %d\n", y0, y1, u, v); |
244 | } |
245 | *dst = (y1 << 24) | (v << 16) | (y0 << 8) | u; |
246 | } |
247 | } |
248 | |
2e6189bc |
249 | /* XXX: missing SDL_LockSurface() */ |
7badc935 |
250 | void *plat_gvideo_flip(void) |
251 | { |
a8376201 |
252 | if (!in_menu && overlay != NULL) { |
253 | SDL_Rect dstrect = { 0, 0, screen->w, screen->h }; |
254 | SDL_LockYUVOverlay(overlay); |
255 | test_convert(overlay->pixels[0], screen->pixels, overlay->w * overlay->h); |
256 | SDL_UnlockYUVOverlay(overlay); |
257 | SDL_DisplayYUVOverlay(overlay, &dstrect); |
258 | } |
259 | else |
260 | SDL_Flip(screen); |
261 | |
262 | if (pending_resize || g_fullscreen != old_fullscreen) { |
263 | // must be done here so that correct buffer is returned |
264 | change_video_mode(psx_w, psx_h); |
265 | pending_resize = 0; |
266 | } |
267 | |
7badc935 |
268 | return screen->pixels; |
269 | } |
270 | |
271 | void plat_gvideo_close(void) |
272 | { |
273 | } |
274 | |
275 | void plat_video_menu_enter(int is_rom_loaded) |
276 | { |
a8376201 |
277 | in_menu = 1; |
278 | |
2e6189bc |
279 | /* surface will be lost, must adjust pl_vout_buf for menu bg */ |
a8376201 |
280 | // FIXME? |
281 | memcpy(menubg_img, screen->pixels, psx_w * psx_h * 2); |
2e6189bc |
282 | pl_vout_buf = menubg_img; |
283 | |
7badc935 |
284 | change_video_mode(g_menuscreen_w, g_menuscreen_h); |
285 | } |
286 | |
287 | void plat_video_menu_begin(void) |
288 | { |
289 | SDL_LockSurface(screen); |
290 | g_menuscreen_ptr = screen->pixels; |
291 | } |
292 | |
293 | void plat_video_menu_end(void) |
294 | { |
295 | SDL_UnlockSurface(screen); |
296 | SDL_Flip(screen); |
297 | g_menuscreen_ptr = NULL; |
298 | } |
299 | |
300 | void plat_video_menu_leave(void) |
301 | { |
a8376201 |
302 | in_menu = 0; |
7badc935 |
303 | } |
304 | |
305 | /* unused stuff */ |
306 | void *plat_prepare_screenshot(int *w, int *h, int *bpp) |
307 | { |
308 | return 0; |
309 | } |
310 | |
7badc935 |
311 | void plat_trigger_vibrate(int is_strong) |
312 | { |
313 | } |
314 | |
315 | void plat_minimize(void) |
316 | { |
317 | } |
318 | |
319 | // vim:shiftwidth=2:expandtab |