pandora: fix readme and pxml version
[picodrive.git] / platform / common / plat_sdl.c
CommitLineData
636d5f25 1/*
2 * PicoDrive
3 * (C) notaz, 2013
7bf552b5 4 * (C) irixxxx, 2020-2024
636d5f25 5 *
6 * This work is licensed under the terms of MAME license.
7 * See COPYING file in the top-level directory.
8 */
9
10#include <stdio.h>
11
12#include "../libpicofe/input.h"
758abbeb 13#include "../libpicofe/plat.h"
636d5f25 14#include "../libpicofe/plat_sdl.h"
15#include "../libpicofe/in_sdl.h"
16#include "../libpicofe/gl.h"
17#include "emu.h"
18#include "menu_pico.h"
19#include "input_pico.h"
b437951a 20#include "plat_sdl.h"
636d5f25 21#include "version.h"
22
57c5a5e5 23#include <pico/pico_int.h>
74e770b1 24
636d5f25 25static void *shadow_fb;
f8aaa200 26static int shadow_size;
d5d17782 27static struct area { int w, h; } area;
636d5f25 28
c12b126f 29static struct in_pdata in_sdl_platform_data;
4e3551a5 30
037f58e1 31static int hide_cursor;
32
089f516d 33static int sound_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 53000, -1 };
34struct plat_target plat_target = { .sound_rates = sound_rates };
58fc34b1 35
36#if defined __MIYOO__
37const char *plat_device = "miyoo";
38#elif defined __GCW0__
39const char *plat_device = "gcw0";
40#elif defined __RETROFW__
41const char *plat_device = "retrofw";
42#elif defined __DINGUX__
43const char *plat_device = "dingux";
44#else
45const char *plat_device = "";
46#endif
47
48int plat_parse_arg(int argc, char *argv[], int *x)
49{
50#if defined __OPENDINGUX__
51 if (*plat_device == '\0' && strcasecmp(argv[*x], "-device") == 0) {
52 plat_device = argv[++(*x)];
53 return 0;
54 }
55#endif
56 return 1;
57}
58
59void plat_early_init(void)
60{
61}
62
63int plat_target_init(void)
64{
65#if defined __ODBETA__
66 if (*plat_device == '\0') {
67 /* ODbeta should always have a device tree, get the model info from there */
68 FILE *f = fopen("/proc/device-tree/compatible", "r");
69 if (f) {
70 char buf[10];
71 int c = fread(buf, 1, sizeof(buf), f);
72 if (strncmp(buf, "gcw,", 4) == 0)
73 plat_device = "gcw0";
74 }
75 }
76#endif
77 return 0;
78}
79
80void plat_target_finish(void)
81{
82}
83
636d5f25 84/* YUV stuff */
85static int yuv_ry[32], yuv_gy[32], yuv_by[32];
86static unsigned char yuv_u[32 * 2], yuv_v[32 * 2];
f740428b 87static unsigned char yuv_y[256];
f821bb70 88static struct uyvy { uint32_t y:8; uint32_t vyu:24; } yuv_uyvy[65536];
636d5f25 89
90void bgr_to_uyvy_init(void)
91{
d80cb20b 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 // valid Y range seems to be 16..235
120 for (i = 0; i < 256; i++) {
121 yuv_y[i] = 16 + 219 * i / 32;
122 }
123 // everything combined into one large array for speed
124 for (i = 0; i < 65536; i++) {
125 int r = (i >> 11) & 0x1f, g = (i >> 6) & 0x1f, b = (i >> 0) & 0x1f;
126 int y = (yuv_ry[r] + yuv_gy[g] + yuv_by[b]) >> 16;
127 yuv_uyvy[i].y = yuv_y[y];
57c5a5e5 128#if CPU_IS_LE
d80cb20b 129 yuv_uyvy[i].vyu = (yuv_v[r-y + 32] << 16) | (yuv_y[y] << 8) | yuv_u[b-y + 32];
57c5a5e5 130#else
d80cb20b 131 yuv_uyvy[i].vyu = (yuv_v[b-y + 32] << 16) | (yuv_y[y] << 8) | yuv_u[r-y + 32];
57c5a5e5 132#endif
d80cb20b 133 }
636d5f25 134}
135
f8aaa200 136void rgb565_to_uyvy(void *d, const void *s, int w, int h, int pitch, int dpitch, int x2)
636d5f25 137{
d80cb20b 138 uint32_t *dst = d;
139 const uint16_t *src = s;
140 int i;
141
142 if (x2) while (h--) {
143 for (i = w; i >= 4; src += 4, dst += 4, i -= 4)
144 {
145 struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
146 struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
57c5a5e5 147#if CPU_IS_LE
d80cb20b 148 dst[0] = (uyvy0->y << 24) | uyvy0->vyu;
149 dst[1] = (uyvy1->y << 24) | uyvy1->vyu;
150 dst[2] = (uyvy2->y << 24) | uyvy2->vyu;
151 dst[3] = (uyvy3->y << 24) | uyvy3->vyu;
57c5a5e5 152#else
d80cb20b 153 dst[0] = uyvy0->y | (uyvy0->vyu << 8);
154 dst[1] = uyvy1->y | (uyvy1->vyu << 8);
155 dst[2] = uyvy2->y | (uyvy2->vyu << 8);
156 dst[3] = uyvy3->y | (uyvy3->vyu << 8);
57c5a5e5 157#endif
d80cb20b 158 }
159 src += pitch - (w-i);
160 dst += (dpitch - 2*(w-i))/2;
161 } else while (h--) {
162 for (i = w; i >= 4; src += 4, dst += 2, i -= 4)
163 {
164 struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
165 struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
57c5a5e5 166#if CPU_IS_LE
d80cb20b 167 dst[0] = (uyvy1->y << 24) | uyvy0->vyu;
168 dst[1] = (uyvy3->y << 24) | uyvy2->vyu;
57c5a5e5 169#else
d80cb20b 170 dst[0] = uyvy1->y | (uyvy0->vyu << 8);
171 dst[1] = uyvy3->y | (uyvy2->vyu << 8);
57c5a5e5 172#endif
d80cb20b 173 }
174 src += pitch - (w-i);
175 dst += (dpitch - (w-i))/2;
176 }
636d5f25 177}
178
e0a346ce 179void copy_intscale(void *dst, int w, int h, int pp, void *src, int sw, int sh, int spp)
180{
44ab042f 181 int xf = w / sw, yf = h / sh, f = xf < yf ? xf : yf;
182 int wf = f * sw, hf = f * sh;
183 int x = (w - wf)/2, y = (h - hf)/2;
e0a346ce 184 uint16_t *p = (uint16_t *)dst;
185 uint16_t *q = (uint16_t *)src;
186
187 // copy 16bit image with scaling by an integer factor
188 int i, j, k, l;
189 p += y * pp + x;
190 for (i = 0; i < sh; i++) {
191 for (j = 0; j < sw; j++, q++)
192 for (l = 0; l < f; l++)
193 *p++ = *q;
44ab042f 194 p += pp - wf;
e0a346ce 195 q += spp - sw;
196 for (k = 1; k < f; k++) {
44ab042f 197 memcpy(p, p-pp, wf*2);
e0a346ce 198 p += pp;
199 }
200 }
201}
202
69b7b264 203static int clear_buf_cnt, clear_stat_cnt;
204
f8aaa200 205static void resize_buffers(void)
206{
207 // make sure the shadow buffers are big enough in case of resize
208 if (shadow_size < g_menuscreen_w * g_menuscreen_h * 2) {
209 shadow_size = g_menuscreen_w * g_menuscreen_h * 2;
210 shadow_fb = realloc(shadow_fb, shadow_size);
211 g_menubg_ptr = realloc(g_menubg_ptr, shadow_size);
212 }
213}
214
d5d17782 215void plat_video_set_size(int w, int h)
216{
61d9a6ee 217 if ((plat_sdl_overlay || plat_sdl_gl_active) && w <= 320 && h <= 240) {
218 // scale to the window, but mind aspect ratio (scaled to 4:3):
219 // w *= win_aspect / 4:3_aspect or h *= 4:3_aspect / win_aspect
d80cb20b 220 if (g_menuscreen_w * 3/4 >= g_menuscreen_h)
e0a346ce 221 w = (w * 3 * g_menuscreen_w/g_menuscreen_h)/4 & ~1;
222 else
223 h = (h * 4 * g_menuscreen_h/g_menuscreen_w)/3 & ~1;
224 }
225
d5d17782 226 if (area.w != w || area.h != h) {
c989b8fe 227 area = (struct area) { w, h };
e0a346ce 228
229 if (plat_sdl_overlay || plat_sdl_gl_active || !plat_sdl_is_windowed()) {
230 // create surface for overlays, or try using a hw scaler
231 if (plat_sdl_change_video_mode(w, h, 0) < 0) {
232 // failed, revert to original resolution
233 area = (struct area) { g_screen_width,g_screen_height };
234 plat_sdl_change_video_mode(g_screen_width, g_screen_height, 0);
235 }
d5d17782 236 }
40a37ac3 237 if (plat_sdl_overlay || plat_sdl_gl_active) {
238 // use shadow buffer for overlays
e0a346ce 239 g_screen_width = area.w;
240 g_screen_height = area.h;
241 g_screen_ppitch = area.w;
242 g_screen_ptr = shadow_fb;
40a37ac3 243 } else if (plat_sdl_is_windowed() &&
244 (plat_sdl_screen->w >= 320*2 || plat_sdl_screen->h >= 240*2 ||
245 plat_sdl_screen->w < 320 || plat_sdl_screen->h < 240)) {
246 // shadow buffer for integer scaling
247 g_screen_width = 320;
248 g_screen_height = 240;
249 g_screen_ppitch = 320;
250 g_screen_ptr = shadow_fb;
e0a346ce 251 } else {
252 // unscaled SDL window buffer can be used directly
f8aaa200 253 g_screen_width = plat_sdl_screen->w;
254 g_screen_height = plat_sdl_screen->h;
255 g_screen_ppitch = plat_sdl_screen->pitch/2;
256 g_screen_ptr = plat_sdl_screen->pixels;
d5d17782 257 }
258 }
259}
260
5aa57006 261void plat_video_set_shadow(int w, int h)
262{
263 g_screen_width = w;
264 g_screen_height = h;
265 g_screen_ppitch = w;
266 g_screen_ptr = shadow_fb;
267}
268
636d5f25 269void plat_video_flip(void)
270{
f8aaa200 271 resize_buffers();
272
636d5f25 273 if (plat_sdl_overlay != NULL) {
274 SDL_Rect dstrect =
275 { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
636d5f25 276 SDL_LockYUVOverlay(plat_sdl_overlay);
f8aaa200 277 if (area.w <= plat_sdl_overlay->w && area.h <= plat_sdl_overlay->h)
278 rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
279 area.w, area.h, g_screen_ppitch,
280 plat_sdl_overlay->pitches[0]/2,
281 plat_sdl_overlay->w >= 2*area.w);
636d5f25 282 SDL_UnlockYUVOverlay(plat_sdl_overlay);
283 SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
284 }
285 else if (plat_sdl_gl_active) {
9cdfc191 286 gl_flip(shadow_fb, g_screen_ppitch, g_screen_height);
636d5f25 287 }
288 else {
e0a346ce 289 int copy = g_screen_ptr != plat_sdl_screen->pixels;
290 if (copy)
291 copy_intscale(plat_sdl_screen->pixels, plat_sdl_screen->w,
292 plat_sdl_screen->h, plat_sdl_screen->pitch/2,
40a37ac3 293 shadow_fb, g_screen_width, g_screen_height, g_screen_ppitch);
e0a346ce 294
295 if (SDL_MUSTLOCK(plat_sdl_screen))
eb7ce29e 296 SDL_UnlockSurface(plat_sdl_screen);
e0a346ce 297 SDL_Flip(plat_sdl_screen);
e0a346ce 298
d80cb20b 299 // take over resized settings for the physical SDL surface
300 if ((plat_sdl_screen->w != g_menuscreen_w ||
301 plat_sdl_screen->h != g_menuscreen_h) && plat_sdl_is_windowed() &&
302 SDL_WM_GrabInput(SDL_GRAB_ON) == SDL_GRAB_ON) {
a51177a4 303 plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, -1);
d80cb20b 304 SDL_WM_GrabInput(SDL_GRAB_OFF);
305 g_menuscreen_pp = plat_sdl_screen->pitch/2;
306
307 // force upper layer to use new dimensions
308 plat_video_set_shadow(g_screen_width, g_screen_height);
309 plat_video_set_buffer(g_screen_ptr);
310 rendstatus_old = -1;
311 } else if (!copy) {
e0a346ce 312 g_screen_ppitch = plat_sdl_screen->pitch/2;
313 g_screen_ptr = plat_sdl_screen->pixels;
314 plat_video_set_buffer(g_screen_ptr);
315 }
316
d80cb20b 317 if (SDL_MUSTLOCK(plat_sdl_screen))
318 SDL_LockSurface(plat_sdl_screen);
319
69b7b264 320 if (clear_buf_cnt) {
61d9a6ee 321 memset(plat_sdl_screen->pixels, 0, plat_sdl_screen->pitch*plat_sdl_screen->h);
69b7b264 322 clear_buf_cnt--;
323 }
324 }
f8aaa200 325
326 // for overlay/gl modes buffer ptr may change on resize
327 if ((plat_sdl_overlay || plat_sdl_gl_active) &&
328 (g_screen_ptr != shadow_fb || g_screen_ppitch != g_screen_width)) {
329 g_screen_ppitch = g_screen_width;
330 g_screen_ptr = shadow_fb;
331 plat_video_set_buffer(g_screen_ptr);
332 }
69b7b264 333 if (clear_stat_cnt) {
334 unsigned short *d = (unsigned short *)g_screen_ptr + g_screen_ppitch * g_screen_height;
335 int l = g_screen_ppitch * 8;
336 memset((int *)(d - l), 0, l * 2);
337 clear_stat_cnt--;
636d5f25 338 }
339}
340
341void plat_video_wait_vsync(void)
342{
343}
344
69b7b264 345void plat_video_clear_status(void)
346{
347 clear_stat_cnt = 3; // do it thrice in case of triple buffering
348}
349
350void plat_video_clear_buffers(void)
351{
61d9a6ee 352 int count = g_menuscreen_w * g_menuscreen_h;
353 if (count < area.w * area.h) count = area.w * area.h;
354 memset(shadow_fb, 0, count * 2);
355 if (plat_sdl_overlay)
356 plat_sdl_overlay_clear();
8b3c1025 357 memset(plat_sdl_screen->pixels, 0, plat_sdl_screen->pitch*plat_sdl_screen->h);
358 clear_buf_cnt = 3; // do it thrice in case of triple buffering
69b7b264 359}
360
7f4bfa96 361void plat_video_menu_update(void)
362{
d80cb20b 363 // WM may grab input while resizing the window; our own window resizing
364 // is only safe if the WM isn't active anymore, so try to grab input.
365 if (plat_sdl_is_windowed() && SDL_WM_GrabInput(SDL_GRAB_ON) == SDL_GRAB_ON) {
366 // w/h might change in resize callback
367 int w, h;
368 do {
369 w = g_menuscreen_w, h = g_menuscreen_h;
a51177a4 370 plat_sdl_change_video_mode(w, h, -1);
d80cb20b 371 } while (w != g_menuscreen_w || h != g_menuscreen_h);
372 SDL_WM_GrabInput(SDL_GRAB_OFF);
373 }
7f4bfa96 374
375 // update pitch as it is needed by the menu bg scaler
376 if (plat_sdl_overlay || plat_sdl_gl_active)
377 g_menuscreen_pp = g_menuscreen_w;
378 else
379 g_menuscreen_pp = plat_sdl_screen->pitch / 2;
61d9a6ee 380
381 resize_buffers();
7f4bfa96 382}
383
636d5f25 384void plat_video_menu_enter(int is_rom_loaded)
385{
758abbeb 386 if (SDL_MUSTLOCK(plat_sdl_screen))
387 SDL_UnlockSurface(plat_sdl_screen);
636d5f25 388}
389
390void plat_video_menu_begin(void)
391{
7f4bfa96 392 plat_video_menu_update(); // just in case
393
394 if (plat_sdl_overlay || plat_sdl_gl_active)
636d5f25 395 g_menuscreen_ptr = shadow_fb;
636d5f25 396 else {
eb7ce29e
PC
397 if (SDL_MUSTLOCK(plat_sdl_screen))
398 SDL_LockSurface(plat_sdl_screen);
636d5f25 399 g_menuscreen_ptr = plat_sdl_screen->pixels;
400 }
401}
402
403void plat_video_menu_end(void)
404{
405 if (plat_sdl_overlay != NULL) {
406 SDL_Rect dstrect =
407 { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
408
409 SDL_LockYUVOverlay(plat_sdl_overlay);
f8aaa200 410 if (g_menuscreen_w <= plat_sdl_overlay->w && g_menuscreen_h <= plat_sdl_overlay->h)
411 rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
412 g_menuscreen_w, g_menuscreen_h, g_menuscreen_pp,
413 plat_sdl_overlay->pitches[0]/2,
414 plat_sdl_overlay->w >= 2 * g_menuscreen_w);
636d5f25 415 SDL_UnlockYUVOverlay(plat_sdl_overlay);
416
417 SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
418 }
419 else if (plat_sdl_gl_active) {
9cdfc191 420 gl_flip(g_menuscreen_ptr, g_menuscreen_pp, g_menuscreen_h);
636d5f25 421 }
422 else {
eb7ce29e
PC
423 if (SDL_MUSTLOCK(plat_sdl_screen))
424 SDL_UnlockSurface(plat_sdl_screen);
636d5f25 425 SDL_Flip(plat_sdl_screen);
426 }
427 g_menuscreen_ptr = NULL;
636d5f25 428}
429
430void plat_video_menu_leave(void)
431{
432}
433
434void plat_video_loop_prepare(void)
435{
61d9a6ee 436 int w = g_menuscreen_w, h = g_menuscreen_h;
437
d5d17782 438 // take over any new vout settings
d80cb20b 439 area = (struct area) { 0, 0 };
f8aaa200 440 plat_sdl_change_video_mode(0, 0, 0);
f8aaa200 441 resize_buffers();
442
ce79590a 443 // switch over to scaled output if available, but keep the aspect ratio
61d9a6ee 444 if (plat_sdl_overlay || plat_sdl_gl_active)
445 w = 320, h = 240;
e0a346ce 446
61d9a6ee 447 g_screen_width = w, g_screen_height = h;
448 plat_video_set_size(w, h);
449
450 if (!(plat_sdl_overlay || plat_sdl_gl_active))
b053cb20 451 if (SDL_MUSTLOCK(plat_sdl_screen))
452 SDL_LockSurface(plat_sdl_screen);
f8aaa200 453
f8aaa200 454 plat_video_set_buffer(g_screen_ptr);
636d5f25 455}
456
037f58e1 457void plat_show_cursor(int on)
458{
459 SDL_ShowCursor(on && !hide_cursor);
460}
461
1777b86d 462int plat_grab_cursor(int on)
037f58e1 463{
464 SDL_WM_GrabInput(on ? SDL_GRAB_ON : SDL_GRAB_OFF);
1777b86d 465 return on;
466}
467
468int plat_has_wm(void)
469{
470 return plat_sdl_is_windowed();
037f58e1 471}
472
f8aaa200 473static void plat_sdl_resize(int w, int h)
474{
475 // take over new settings
83093596 476#if defined(__OPENDINGUX__)
e0a346ce 477 if (currentConfig.vscaling != EOPT_SCALE_HW &&
478 plat_sdl_screen->w == 320 && plat_sdl_screen->h == 480) {
479 g_menuscreen_h = 240;
480 g_menuscreen_w = 320;
481 } else
0e7c5311 482#endif
e0a346ce 483 {
484 g_menuscreen_h = plat_sdl_screen->h;
485 g_menuscreen_w = plat_sdl_screen->w;
8b3c1025 486#if 0 // auto resizing may be nice, but creates problems on some SDL platforms
d80cb20b 487 if (!plat_sdl_overlay && !plat_sdl_gl_active &&
488 plat_sdl_is_windowed() && !plat_sdl_is_fullscreen()) {
489 // in SDL window mode, adapt window to integer scaling
490 if (g_menuscreen_w * 3/4 >= g_menuscreen_h)
491 g_menuscreen_w = g_menuscreen_h * 4/3;
492 else
493 g_menuscreen_h = g_menuscreen_w * 3/4;
494 g_menuscreen_w = g_menuscreen_w/320*320;
495 g_menuscreen_h = g_menuscreen_h/240*240;
496 if (g_menuscreen_w == 0) {
497 g_menuscreen_w = 320;
498 g_menuscreen_h = 240;
499 }
500 }
8b3c1025 501#endif
5aa57006 502 }
d80cb20b 503
e0a346ce 504 rendstatus_old = -1;
f8aaa200 505}
506
bec84f92 507static void plat_sdl_quit(void)
508{
509 // for now..
510 exit(1);
511}
512
636d5f25 513void plat_init(void)
514{
636d5f25 515 int ret;
516
517 ret = plat_sdl_init();
518 if (ret != 0)
519 exit(1);
d80cb20b 520
f2554438 521#if defined(__OPENDINGUX__)
758abbeb 522 // opendingux on JZ47x0 may falsely report a HW overlay, fix to window
523 plat_target.vout_method = 0;
d80cb20b 524#elif !defined(__MIYOO__) && !defined(__RETROFW__) && !defined(__DINGUX__)
525 if (! plat_sdl_is_windowed())
758abbeb 526#endif
037f58e1 527 {
528 hide_cursor = 1;
d80cb20b 529 SDL_ShowCursor(0);
037f58e1 530 }
636d5f25 531
bec84f92 532 plat_sdl_quit_cb = plat_sdl_quit;
f8aaa200 533 plat_sdl_resize_cb = plat_sdl_resize;
bec84f92 534
fc11dd05 535 SDL_WM_SetCaption("PicoDrive " VERSION, NULL);
636d5f25 536
9cdfc191 537 g_menuscreen_pp = g_menuscreen_w;
636d5f25 538 g_menuscreen_ptr = NULL;
539
540 shadow_size = g_menuscreen_w * g_menuscreen_h * 2;
541 if (shadow_size < 320 * 480 * 2)
542 shadow_size = 320 * 480 * 2;
543
7a7265ee 544 shadow_fb = calloc(1, shadow_size);
2d2e57b2 545 g_menubg_ptr = calloc(1, shadow_size);
636d5f25 546 if (shadow_fb == NULL || g_menubg_ptr == NULL) {
547 fprintf(stderr, "OOM\n");
548 exit(1);
549 }
550
551 g_screen_width = 320;
552 g_screen_height = 240;
9cdfc191 553 g_screen_ppitch = 320;
636d5f25 554 g_screen_ptr = shadow_fb;
555
58fc34b1 556 plat_target_setup_input();
c12b126f 557 in_sdl_platform_data.defbinds = in_sdl_defbinds,
b437951a 558 in_sdl_platform_data.kmap_size = in_sdl_key_map_sz,
58fc34b1 559 in_sdl_platform_data.key_map = in_sdl_key_map,
b437951a 560 in_sdl_platform_data.jmap_size = in_sdl_joy_map_sz,
58fc34b1 561 in_sdl_platform_data.joy_map = in_sdl_joy_map,
562 in_sdl_platform_data.key_names = in_sdl_key_names,
20c9a3ba 563 in_sdl_platform_data.kbd_map = in_sdl_kbd_map,
4e3551a5 564 in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler);
636d5f25 565 in_probe();
566
0738c83e 567 // create an artificial resize event to initialize mouse scaling
568 SDL_Event ev;
569 ev.resize.type = SDL_VIDEORESIZE;
570 ev.resize.w = g_menuscreen_w;
571 ev.resize.h = g_menuscreen_h;
572 SDL_PeepEvents(&ev, 1, SDL_ADDEVENT, SDL_ALLEVENTS);
573
636d5f25 574 bgr_to_uyvy_init();
85174a6d 575 linux_menu_init();
636d5f25 576}
577
578void plat_finish(void)
579{
580 free(shadow_fb);
581 shadow_fb = NULL;
582 free(g_menubg_ptr);
583 g_menubg_ptr = NULL;
584 plat_sdl_finish();
585}