Commit | Line | Data |
---|---|---|
636d5f25 | 1 | /* |
2 | * PicoDrive | |
3 | * (C) notaz, 2013 | |
4 | * | |
5 | * This work is licensed under the terms of MAME license. | |
6 | * See COPYING file in the top-level directory. | |
7 | */ | |
8 | ||
9 | #include <stdio.h> | |
10 | ||
11 | #include "../libpicofe/input.h" | |
12 | #include "../libpicofe/plat_sdl.h" | |
13 | #include "../libpicofe/in_sdl.h" | |
14 | #include "../libpicofe/gl.h" | |
15 | #include "emu.h" | |
16 | #include "menu_pico.h" | |
17 | #include "input_pico.h" | |
18 | #include "version.h" | |
19 | ||
636d5f25 | 20 | static void *shadow_fb; |
21 | ||
4e3551a5 | 22 | const struct in_default_bind in_sdl_defbinds[] __attribute__((weak)) = { |
636d5f25 | 23 | { SDLK_UP, IN_BINDTYPE_PLAYER12, GBTN_UP }, |
24 | { SDLK_DOWN, IN_BINDTYPE_PLAYER12, GBTN_DOWN }, | |
25 | { SDLK_LEFT, IN_BINDTYPE_PLAYER12, GBTN_LEFT }, | |
26 | { SDLK_RIGHT, IN_BINDTYPE_PLAYER12, GBTN_RIGHT }, | |
27 | { SDLK_z, IN_BINDTYPE_PLAYER12, GBTN_A }, | |
28 | { SDLK_x, IN_BINDTYPE_PLAYER12, GBTN_B }, | |
29 | { SDLK_c, IN_BINDTYPE_PLAYER12, GBTN_C }, | |
30 | { SDLK_a, IN_BINDTYPE_PLAYER12, GBTN_X }, | |
31 | { SDLK_s, IN_BINDTYPE_PLAYER12, GBTN_Y }, | |
32 | { SDLK_d, IN_BINDTYPE_PLAYER12, GBTN_Z }, | |
33 | { SDLK_RETURN, IN_BINDTYPE_PLAYER12, GBTN_START }, | |
34 | { SDLK_f, IN_BINDTYPE_PLAYER12, GBTN_MODE }, | |
35 | { SDLK_ESCAPE, IN_BINDTYPE_EMU, PEVB_MENU }, | |
36 | { SDLK_F1, IN_BINDTYPE_EMU, PEVB_STATE_SAVE }, | |
37 | { SDLK_F2, IN_BINDTYPE_EMU, PEVB_STATE_LOAD }, | |
38 | { SDLK_F3, IN_BINDTYPE_EMU, PEVB_SSLOT_PREV }, | |
39 | { SDLK_F4, IN_BINDTYPE_EMU, PEVB_SSLOT_NEXT }, | |
40 | { SDLK_F5, IN_BINDTYPE_EMU, PEVB_SWITCH_RND }, | |
41 | { SDLK_F6, IN_BINDTYPE_EMU, PEVB_PICO_PPREV }, | |
42 | { SDLK_F7, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT }, | |
43 | { SDLK_F8, IN_BINDTYPE_EMU, PEVB_PICO_SWINP }, | |
44 | { SDLK_BACKSPACE, IN_BINDTYPE_EMU, PEVB_FF }, | |
45 | { 0, 0, 0 } | |
46 | }; | |
47 | ||
4e3551a5 PC |
48 | const struct menu_keymap in_sdl_key_map[] __attribute__((weak)) = |
49 | { | |
50 | { SDLK_UP, PBTN_UP }, | |
51 | { SDLK_DOWN, PBTN_DOWN }, | |
52 | { SDLK_LEFT, PBTN_LEFT }, | |
53 | { SDLK_RIGHT, PBTN_RIGHT }, | |
54 | { SDLK_RETURN, PBTN_MOK }, | |
55 | { SDLK_ESCAPE, PBTN_MBACK }, | |
56 | { SDLK_SEMICOLON, PBTN_MA2 }, | |
57 | { SDLK_QUOTE, PBTN_MA3 }, | |
58 | { SDLK_LEFTBRACKET, PBTN_L }, | |
59 | { SDLK_RIGHTBRACKET, PBTN_R }, | |
60 | }; | |
61 | ||
62 | const struct menu_keymap in_sdl_joy_map[] __attribute__((weak)) = | |
63 | { | |
64 | { SDLK_UP, PBTN_UP }, | |
65 | { SDLK_DOWN, PBTN_DOWN }, | |
66 | { SDLK_LEFT, PBTN_LEFT }, | |
67 | { SDLK_RIGHT, PBTN_RIGHT }, | |
68 | /* joystick */ | |
69 | { SDLK_WORLD_0, PBTN_MOK }, | |
70 | { SDLK_WORLD_1, PBTN_MBACK }, | |
71 | { SDLK_WORLD_2, PBTN_MA2 }, | |
72 | { SDLK_WORLD_3, PBTN_MA3 }, | |
73 | }; | |
74 | ||
d4bea61c PC |
75 | extern const char * const in_sdl_key_names[] __attribute__((weak)); |
76 | ||
4e3551a5 PC |
77 | static const struct in_pdata in_sdl_platform_data = { |
78 | .defbinds = in_sdl_defbinds, | |
79 | .key_map = in_sdl_key_map, | |
80 | .kmap_size = sizeof(in_sdl_key_map) / sizeof(in_sdl_key_map[0]), | |
81 | .joy_map = in_sdl_joy_map, | |
82 | .jmap_size = sizeof(in_sdl_joy_map) / sizeof(in_sdl_joy_map[0]), | |
d4bea61c | 83 | .key_names = in_sdl_key_names, |
4e3551a5 PC |
84 | }; |
85 | ||
636d5f25 | 86 | /* YUV stuff */ |
87 | static int yuv_ry[32], yuv_gy[32], yuv_by[32]; | |
88 | static unsigned char yuv_u[32 * 2], yuv_v[32 * 2]; | |
89 | ||
90 | void bgr_to_uyvy_init(void) | |
91 | { | |
92 | int i, v; | |
93 | ||
94 | /* init yuv converter: | |
95 | y0 = (int)((0.299f * r0) + (0.587f * g0) + (0.114f * b0)); | |
96 | y1 = (int)((0.299f * r1) + (0.587f * g1) + (0.114f * b1)); | |
97 | u = (int)(8 * 0.565f * (b0 - y0)) + 128; | |
98 | v = (int)(8 * 0.713f * (r0 - y0)) + 128; | |
99 | */ | |
100 | for (i = 0; i < 32; i++) { | |
101 | yuv_ry[i] = (int)(0.299f * i * 65536.0f + 0.5f); | |
102 | yuv_gy[i] = (int)(0.587f * i * 65536.0f + 0.5f); | |
103 | yuv_by[i] = (int)(0.114f * i * 65536.0f + 0.5f); | |
104 | } | |
105 | for (i = -32; i < 32; i++) { | |
106 | v = (int)(8 * 0.565f * i) + 128; | |
107 | if (v < 0) | |
108 | v = 0; | |
109 | if (v > 255) | |
110 | v = 255; | |
111 | yuv_u[i + 32] = v; | |
112 | v = (int)(8 * 0.713f * i) + 128; | |
113 | if (v < 0) | |
114 | v = 0; | |
115 | if (v > 255) | |
116 | v = 255; | |
117 | yuv_v[i + 32] = v; | |
118 | } | |
119 | } | |
120 | ||
121 | void rgb565_to_uyvy(void *d, const void *s, int pixels) | |
122 | { | |
123 | unsigned int *dst = d; | |
124 | const unsigned short *src = s; | |
125 | const unsigned char *yu = yuv_u + 32; | |
126 | const unsigned char *yv = yuv_v + 32; | |
127 | int r0, g0, b0, r1, g1, b1; | |
128 | int y0, y1, u, v; | |
129 | ||
130 | for (; pixels > 0; src += 2, dst++, pixels -= 2) | |
131 | { | |
132 | r0 = (src[0] >> 11) & 0x1f; | |
133 | g0 = (src[0] >> 6) & 0x1f; | |
134 | b0 = src[0] & 0x1f; | |
135 | r1 = (src[1] >> 11) & 0x1f; | |
136 | g1 = (src[1] >> 6) & 0x1f; | |
137 | b1 = src[1] & 0x1f; | |
138 | y0 = (yuv_ry[r0] + yuv_gy[g0] + yuv_by[b0]) >> 16; | |
139 | y1 = (yuv_ry[r1] + yuv_gy[g1] + yuv_by[b1]) >> 16; | |
140 | u = yu[b0 - y0]; | |
141 | v = yv[r0 - y0]; | |
142 | // valid Y range seems to be 16..235 | |
143 | y0 = 16 + 219 * y0 / 31; | |
144 | y1 = 16 + 219 * y1 / 31; | |
145 | ||
146 | *dst = (y1 << 24) | (v << 16) | (y0 << 8) | u; | |
147 | } | |
148 | } | |
149 | ||
150 | void plat_video_flip(void) | |
151 | { | |
152 | if (plat_sdl_overlay != NULL) { | |
153 | SDL_Rect dstrect = | |
154 | { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h }; | |
155 | ||
156 | SDL_LockYUVOverlay(plat_sdl_overlay); | |
157 | rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb, | |
158 | g_screen_width * g_screen_height); | |
159 | SDL_UnlockYUVOverlay(plat_sdl_overlay); | |
160 | SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect); | |
161 | } | |
162 | else if (plat_sdl_gl_active) { | |
163 | gl_flip(shadow_fb, g_screen_width, g_screen_height); | |
164 | } | |
165 | else { | |
eb7ce29e PC |
166 | if (SDL_MUSTLOCK(plat_sdl_screen)) |
167 | SDL_UnlockSurface(plat_sdl_screen); | |
636d5f25 | 168 | SDL_Flip(plat_sdl_screen); |
169 | g_screen_ptr = plat_sdl_screen->pixels; | |
eb7ce29e | 170 | PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2); |
636d5f25 | 171 | } |
172 | } | |
173 | ||
174 | void plat_video_wait_vsync(void) | |
175 | { | |
176 | } | |
177 | ||
178 | void plat_video_menu_enter(int is_rom_loaded) | |
179 | { | |
180 | plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 0); | |
d438a8dd | 181 | g_screen_ptr = shadow_fb; |
636d5f25 | 182 | } |
183 | ||
184 | void plat_video_menu_begin(void) | |
185 | { | |
186 | if (plat_sdl_overlay != NULL || plat_sdl_gl_active) { | |
187 | g_menuscreen_ptr = shadow_fb; | |
188 | } | |
189 | else { | |
eb7ce29e PC |
190 | if (SDL_MUSTLOCK(plat_sdl_screen)) |
191 | SDL_LockSurface(plat_sdl_screen); | |
636d5f25 | 192 | g_menuscreen_ptr = plat_sdl_screen->pixels; |
193 | } | |
194 | } | |
195 | ||
196 | void plat_video_menu_end(void) | |
197 | { | |
198 | if (plat_sdl_overlay != NULL) { | |
199 | SDL_Rect dstrect = | |
200 | { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h }; | |
201 | ||
202 | SDL_LockYUVOverlay(plat_sdl_overlay); | |
203 | rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb, | |
204 | g_menuscreen_w * g_menuscreen_h); | |
205 | SDL_UnlockYUVOverlay(plat_sdl_overlay); | |
206 | ||
207 | SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect); | |
208 | } | |
209 | else if (plat_sdl_gl_active) { | |
210 | gl_flip(g_menuscreen_ptr, g_menuscreen_w, g_menuscreen_h); | |
211 | } | |
212 | else { | |
eb7ce29e PC |
213 | if (SDL_MUSTLOCK(plat_sdl_screen)) |
214 | SDL_UnlockSurface(plat_sdl_screen); | |
636d5f25 | 215 | SDL_Flip(plat_sdl_screen); |
216 | } | |
217 | g_menuscreen_ptr = NULL; | |
218 | ||
219 | } | |
220 | ||
221 | void plat_video_menu_leave(void) | |
222 | { | |
223 | } | |
224 | ||
225 | void plat_video_loop_prepare(void) | |
226 | { | |
227 | plat_sdl_change_video_mode(g_screen_width, g_screen_height, 0); | |
228 | ||
229 | if (plat_sdl_overlay != NULL || plat_sdl_gl_active) { | |
230 | g_screen_ptr = shadow_fb; | |
231 | } | |
232 | else { | |
eb7ce29e PC |
233 | if (SDL_MUSTLOCK(plat_sdl_screen)) |
234 | SDL_LockSurface(plat_sdl_screen); | |
636d5f25 | 235 | g_screen_ptr = plat_sdl_screen->pixels; |
236 | } | |
eb7ce29e | 237 | PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2); |
636d5f25 | 238 | } |
239 | ||
240 | void plat_early_init(void) | |
241 | { | |
242 | } | |
243 | ||
bec84f92 | 244 | static void plat_sdl_quit(void) |
245 | { | |
246 | // for now.. | |
247 | exit(1); | |
248 | } | |
249 | ||
636d5f25 | 250 | void plat_init(void) |
251 | { | |
252 | int shadow_size; | |
253 | int ret; | |
254 | ||
255 | ret = plat_sdl_init(); | |
256 | if (ret != 0) | |
257 | exit(1); | |
258 | ||
bec84f92 | 259 | plat_sdl_quit_cb = plat_sdl_quit; |
260 | ||
fc11dd05 | 261 | SDL_WM_SetCaption("PicoDrive " VERSION, NULL); |
636d5f25 | 262 | |
263 | g_menuscreen_w = plat_sdl_screen->w; | |
264 | g_menuscreen_h = plat_sdl_screen->h; | |
265 | g_menuscreen_ptr = NULL; | |
266 | ||
267 | shadow_size = g_menuscreen_w * g_menuscreen_h * 2; | |
268 | if (shadow_size < 320 * 480 * 2) | |
269 | shadow_size = 320 * 480 * 2; | |
270 | ||
271 | shadow_fb = malloc(shadow_size); | |
272 | g_menubg_ptr = malloc(shadow_size); | |
273 | if (shadow_fb == NULL || g_menubg_ptr == NULL) { | |
274 | fprintf(stderr, "OOM\n"); | |
275 | exit(1); | |
276 | } | |
277 | ||
278 | g_screen_width = 320; | |
279 | g_screen_height = 240; | |
280 | g_screen_ptr = shadow_fb; | |
281 | ||
4e3551a5 | 282 | in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler); |
636d5f25 | 283 | in_probe(); |
284 | ||
285 | bgr_to_uyvy_init(); | |
286 | } | |
287 | ||
288 | void plat_finish(void) | |
289 | { | |
290 | free(shadow_fb); | |
291 | shadow_fb = NULL; | |
292 | free(g_menubg_ptr); | |
293 | g_menubg_ptr = NULL; | |
294 | plat_sdl_finish(); | |
295 | } |