ec2d9c24ab6270e82794e8b97827a9a337ef5000
[pcsx_rearmed.git] / frontend / plat_sdl.c
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>
13
14 #include "libpicofe/input.h"
15 #include "libpicofe/in_sdl.h"
16 #include "libpicofe/menu.h"
17 #include "libpicofe/fonts.h"
18 #include "libpicofe/plat_sdl.h"
19 #include "libpicofe/gl.h"
20 #include "../plugins/gpulib/cspace.h"
21 #include "plugin_lib.h"
22 #include "main.h"
23 #include "plat.h"
24 #include "revision.h"
25
26 static const struct in_default_bind in_sdl_defbinds[] = {
27   { SDLK_UP,     IN_BINDTYPE_PLAYER12, DKEY_UP },
28   { SDLK_DOWN,   IN_BINDTYPE_PLAYER12, DKEY_DOWN },
29   { SDLK_LEFT,   IN_BINDTYPE_PLAYER12, DKEY_LEFT },
30   { SDLK_RIGHT,  IN_BINDTYPE_PLAYER12, DKEY_RIGHT },
31   { SDLK_d,      IN_BINDTYPE_PLAYER12, DKEY_TRIANGLE },
32   { SDLK_z,      IN_BINDTYPE_PLAYER12, DKEY_CROSS },
33   { SDLK_x,      IN_BINDTYPE_PLAYER12, DKEY_CIRCLE },
34   { SDLK_s,      IN_BINDTYPE_PLAYER12, DKEY_SQUARE },
35   { SDLK_v,      IN_BINDTYPE_PLAYER12, DKEY_START },
36   { SDLK_c,      IN_BINDTYPE_PLAYER12, DKEY_SELECT },
37   { SDLK_w,      IN_BINDTYPE_PLAYER12, DKEY_L1 },
38   { SDLK_r,      IN_BINDTYPE_PLAYER12, DKEY_R1 },
39   { SDLK_e,      IN_BINDTYPE_PLAYER12, DKEY_L2 },
40   { SDLK_t,      IN_BINDTYPE_PLAYER12, DKEY_R2 },
41   { SDLK_ESCAPE, IN_BINDTYPE_EMU, SACTION_ENTER_MENU },
42   { SDLK_F1,     IN_BINDTYPE_EMU, SACTION_SAVE_STATE },
43   { SDLK_F2,     IN_BINDTYPE_EMU, SACTION_LOAD_STATE },
44   { SDLK_F3,     IN_BINDTYPE_EMU, SACTION_PREV_SSLOT },
45   { SDLK_F4,     IN_BINDTYPE_EMU, SACTION_NEXT_SSLOT },
46   { SDLK_F5,     IN_BINDTYPE_EMU, SACTION_TOGGLE_FSKIP },
47   { SDLK_F6,     IN_BINDTYPE_EMU, SACTION_SCREENSHOT },
48   { SDLK_F7,     IN_BINDTYPE_EMU, SACTION_TOGGLE_FPS },
49   { SDLK_F8,     IN_BINDTYPE_EMU, SACTION_SWITCH_DISPMODE },
50   { SDLK_F11,    IN_BINDTYPE_EMU, SACTION_TOGGLE_FULLSCREEN },
51   { SDLK_BACKSPACE, IN_BINDTYPE_EMU, SACTION_FAST_FORWARD },
52   { 0, 0, 0 }
53 };
54
55 static int psx_w, psx_h;
56 static void *shadow_fb, *menubg_img;
57 static int in_menu;
58
59 static int change_video_mode(void)
60 {
61   int w, h;
62
63   if (in_menu) {
64     w = g_menuscreen_w;
65     h = g_menuscreen_h;
66   }
67   else {
68     w = psx_w;
69     h = psx_h;
70   }
71
72   return plat_sdl_change_video_mode(w, h);
73 }
74
75 void plat_init(void)
76 {
77   int ret;
78
79   ret = plat_sdl_init();
80   if (ret != 0)
81     exit(1);
82
83   in_menu = 1;
84   SDL_WM_SetCaption("PCSX-ReARMed " REV, NULL);
85
86   shadow_fb = malloc(640 * 512 * 2);
87   menubg_img = malloc(640 * 512 * 2);
88   if (shadow_fb == NULL || menubg_img == NULL) {
89     fprintf(stderr, "OOM\n");
90     exit(1);
91   }
92
93   in_sdl_init(in_sdl_defbinds, plat_sdl_event_handler);
94   in_probe();
95   pl_rearmed_cbs.only_16bpp = 1;
96
97   bgr_to_uyvy_init();
98 }
99
100 void plat_finish(void)
101 {
102   free(shadow_fb);
103   shadow_fb = NULL;
104   free(menubg_img);
105   menubg_img = NULL;
106   plat_sdl_finish();
107 }
108
109 void plat_gvideo_open(int is_pal)
110 {
111 }
112
113 static void uyvy_to_rgb565(void *d, const void *s, int pixels)
114 {
115   unsigned short *dst = d;
116   const unsigned int *src = s;
117   int v;
118
119   // no colors, for now
120   for (; pixels > 0; src++, dst += 2, pixels -= 2) {
121     v = (*src >> 8) & 0xff;
122     v = (v - 16) * 255 / 219 / 8;
123     dst[0] = (v << 11) | (v << 6) | v;
124
125     v = (*src >> 24) & 0xff;
126     v = (v - 16) * 255 / 219 / 8;
127     dst[1] = (v << 11) | (v << 6) | v;
128   }
129 }
130
131 static void overlay_blit(int doffs, const void *src_, int w, int h,
132                          int sstride, int bgr24)
133 {
134   const unsigned short *src = src_;
135   unsigned short *dst;
136   int dstride = plat_sdl_overlay->w;
137
138   SDL_LockYUVOverlay(plat_sdl_overlay);
139   dst = (void *)plat_sdl_overlay->pixels[0];
140
141   dst += doffs;
142   if (bgr24) {
143     for (; h > 0; dst += dstride, src += sstride, h--)
144       bgr888_to_uyvy(dst, src, w);
145   }
146   else {
147     for (; h > 0; dst += dstride, src += sstride, h--)
148       bgr555_to_uyvy(dst, src, w);
149   }
150
151   SDL_UnlockYUVOverlay(plat_sdl_overlay);
152 }
153
154 static void overlay_hud_print(int x, int y, const char *str, int bpp)
155 {
156   SDL_LockYUVOverlay(plat_sdl_overlay);
157   basic_text_out_uyvy_nf(plat_sdl_overlay->pixels[0], plat_sdl_overlay->w, x, y, str);
158   SDL_UnlockYUVOverlay(plat_sdl_overlay);
159 }
160
161 void *plat_gvideo_set_mode(int *w, int *h, int *bpp)
162 {
163   psx_w = *w;
164   psx_h = *h;
165   change_video_mode();
166   if (plat_sdl_overlay != NULL) {
167     pl_plat_clear = plat_sdl_overlay_clear;
168     pl_plat_blit = overlay_blit;
169     pl_plat_hud_print = overlay_hud_print;
170     return NULL;
171   }
172   else {
173     pl_plat_clear = NULL;
174     pl_plat_blit = NULL;
175     pl_plat_hud_print = NULL;
176     if (plat_sdl_gl_active)
177       return shadow_fb;
178     else
179       return plat_sdl_screen->pixels;
180   }
181 }
182
183 void *plat_gvideo_flip(void)
184 {
185   if (plat_sdl_overlay != NULL) {
186     SDL_Rect dstrect = { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
187     SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
188     return NULL;
189   }
190   else if (plat_sdl_gl_active) {
191     gl_flip(shadow_fb, psx_w, psx_h);
192     return shadow_fb;
193   }
194   else {
195     // XXX: no locking, but should be fine with SDL_SWSURFACE?
196     SDL_Flip(plat_sdl_screen);
197     return plat_sdl_screen->pixels;
198   }
199 }
200
201 void plat_gvideo_close(void)
202 {
203 }
204
205 void plat_video_menu_enter(int is_rom_loaded)
206 {
207   in_menu = 1;
208
209   /* surface will be lost, must adjust pl_vout_buf for menu bg */
210   if (plat_sdl_overlay != NULL)
211     uyvy_to_rgb565(menubg_img, plat_sdl_overlay->pixels[0], psx_w * psx_h);
212   else if (plat_sdl_gl_active)
213     memcpy(menubg_img, shadow_fb, psx_w * psx_h * 2);
214   else
215     memcpy(menubg_img, plat_sdl_screen->pixels, psx_w * psx_h * 2);
216   pl_vout_buf = menubg_img;
217
218   change_video_mode();
219 }
220
221 void plat_video_menu_begin(void)
222 {
223   if (plat_sdl_overlay != NULL || plat_sdl_gl_active) {
224     g_menuscreen_ptr = shadow_fb;
225   }
226   else {
227     SDL_LockSurface(plat_sdl_screen);
228     g_menuscreen_ptr = plat_sdl_screen->pixels;
229   }
230 }
231
232 void plat_video_menu_end(void)
233 {
234   if (plat_sdl_overlay != NULL) {
235     SDL_Rect dstrect = { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
236
237     SDL_LockYUVOverlay(plat_sdl_overlay);
238     rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
239       g_menuscreen_w * g_menuscreen_h);
240     SDL_UnlockYUVOverlay(plat_sdl_overlay);
241
242     SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
243   }
244   else if (plat_sdl_gl_active) {
245     gl_flip(g_menuscreen_ptr, g_menuscreen_w, g_menuscreen_h);
246   }
247   else {
248     SDL_UnlockSurface(plat_sdl_screen);
249     SDL_Flip(plat_sdl_screen);
250   }
251   g_menuscreen_ptr = NULL;
252 }
253
254 void plat_video_menu_leave(void)
255 {
256   in_menu = 0;
257 }
258
259 /* unused stuff */
260 void *plat_prepare_screenshot(int *w, int *h, int *bpp)
261 {
262   return 0;
263 }
264
265 void plat_trigger_vibrate(int is_strong)
266 {
267 }
268
269 void plat_minimize(void)
270 {
271 }
272
273 // vim:shiftwidth=2:expandtab