platform ps2, handle audio similar to psp
[picodrive.git] / platform / pandora / plat.c
CommitLineData
cff531af 1/*\r
2 * PicoDrive\r
3 * (C) notaz, 2010,2011\r
4 *\r
5 * This work is licensed under the terms of MAME license.\r
6 * See COPYING file in the top-level directory.\r
7 */\r
c7eb229a 8\r
9#include <stdio.h>\r
10#include <unistd.h>\r
c7eb229a 11#include <sys/types.h>\r
12#include <sys/stat.h>\r
13#include <fcntl.h>\r
14#include <sys/ioctl.h>\r
15#include <unistd.h>\r
16#include <linux/fb.h>\r
17#include <linux/omapfb.h>\r
d4d62665 18#include <linux/input.h>\r
c7eb229a 19\r
20#include "../common/emu.h"\r
c7eb229a 21#include "../common/arm_utils.h"\r
d4d62665 22#include "../common/input_pico.h"\r
23#include "../common/version.h"\r
24#include "../libpicofe/input.h"\r
25#include "../libpicofe/menu.h"\r
26#include "../libpicofe/plat.h"\r
27#include "../libpicofe/linux/in_evdev.h"\r
28#include "../libpicofe/linux/sndout_oss.h"\r
29#include "../libpicofe/linux/fbdev.h"\r
30#include "../libpicofe/linux/xenv.h"\r
c7eb229a 31#include "plat.h"\r
32#include "asm_utils.h"\r
c7eb229a 33\r
34#include <pico/pico_int.h>\r
35\r
55d7dcb2 36#define LAYER_MEM_SIZE (320*240*2 * 4)\r
37\r
c7eb229a 38static struct vout_fbdev *main_fb, *layer_fb;\r
21ebcfd3 39// g_layer_* - in use, g_layer_c* - configured custom\r
8a407398 40int g_layer_cx = 80, g_layer_cy, g_layer_cw = 640, g_layer_ch = 480;\r
ca980e1b 41int saved_start_line = 0, saved_line_count = 240;\r
42int saved_start_col = 0, saved_col_count = 320;\r
c7eb229a 43static int g_layer_x, g_layer_y;\r
44static int g_layer_w = 320, g_layer_h = 240;\r
8a407398 45static int g_osd_start_x, g_osd_fps_x, g_osd_y, doing_bg_frame;\r
c7eb229a 46\r
d4d62665 47static unsigned char __attribute__((aligned(4))) fb_copy[320 * 240 * 2];\r
d40231e2 48static void *temp_frame;\r
c7eb229a 49const char *renderer_names[] = { NULL };\r
50const char *renderer_names32x[] = { NULL };\r
c7eb229a 51\r
d4d62665 52static struct in_default_bind in_evdev_defbinds[] =\r
53{\r
54 { KEY_UP, IN_BINDTYPE_PLAYER12, GBTN_UP },\r
55 { KEY_DOWN, IN_BINDTYPE_PLAYER12, GBTN_DOWN },\r
56 { KEY_LEFT, IN_BINDTYPE_PLAYER12, GBTN_LEFT },\r
57 { KEY_RIGHT, IN_BINDTYPE_PLAYER12, GBTN_RIGHT },\r
58 { KEY_A, IN_BINDTYPE_PLAYER12, GBTN_A },\r
59 { KEY_S, IN_BINDTYPE_PLAYER12, GBTN_B },\r
60 { KEY_D, IN_BINDTYPE_PLAYER12, GBTN_C },\r
61 { KEY_ENTER, IN_BINDTYPE_PLAYER12, GBTN_START },\r
9db6a544 62 { KEY_R, IN_BINDTYPE_EMU, PEVB_RESET },\r
b011c2af 63 { KEY_F, IN_BINDTYPE_EMU, PEVB_FF },\r
c7074ddb 64 { KEY_BACKSPACE,IN_BINDTYPE_EMU, PEVB_FF },\r
65 { KEY_BACKSLASH,IN_BINDTYPE_EMU, PEVB_MENU },\r
21ebcfd3 66 { KEY_SPACE, IN_BINDTYPE_EMU, PEVB_MENU },\r
c7074ddb 67 { KEY_LEFTCTRL, IN_BINDTYPE_EMU, PEVB_MENU },\r
d4d62665 68 { KEY_HOME, IN_BINDTYPE_PLAYER12, GBTN_A },\r
69 { KEY_PAGEDOWN, IN_BINDTYPE_PLAYER12, GBTN_B },\r
70 { KEY_END, IN_BINDTYPE_PLAYER12, GBTN_C },\r
71 { KEY_LEFTALT, IN_BINDTYPE_PLAYER12, GBTN_START },\r
c7074ddb 72 { KEY_1, IN_BINDTYPE_EMU, PEVB_STATE_SAVE },\r
73 { KEY_2, IN_BINDTYPE_EMU, PEVB_STATE_LOAD },\r
74 { KEY_3, IN_BINDTYPE_EMU, PEVB_SSLOT_PREV },\r
75 { KEY_4, IN_BINDTYPE_EMU, PEVB_SSLOT_NEXT },\r
76 { KEY_5, IN_BINDTYPE_EMU, PEVB_PICO_PPREV },\r
77 { KEY_6, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT },\r
15cc45c0 78 { KEY_7, IN_BINDTYPE_EMU, PEVB_PICO_STORY },\r
79 { KEY_8, IN_BINDTYPE_EMU, PEVB_PICO_PAD },\r
80 { KEY_9, IN_BINDTYPE_EMU, PEVB_PICO_PENST },\r
21ebcfd3 81 { 0, 0, 0 }\r
82};\r
83\r
4e3551a5
PC
84static const struct menu_keymap key_pbtn_map[] =\r
85{\r
86 { KEY_UP, PBTN_UP },\r
87 { KEY_DOWN, PBTN_DOWN },\r
88 { KEY_LEFT, PBTN_LEFT },\r
89 { KEY_RIGHT, PBTN_RIGHT },\r
90 /* Pandora */\r
91 { KEY_END, PBTN_MOK },\r
92 { KEY_PAGEDOWN, PBTN_MBACK },\r
93 { KEY_HOME, PBTN_MA2 },\r
94 { KEY_PAGEUP, PBTN_MA3 },\r
95 { KEY_LEFTCTRL, PBTN_MENU },\r
96 { KEY_RIGHTSHIFT, PBTN_L },\r
97 { KEY_RIGHTCTRL, PBTN_R },\r
98 /* "normal" keyboards */\r
99 { KEY_ENTER, PBTN_MOK },\r
100 { KEY_ESC, PBTN_MBACK },\r
101 { KEY_SEMICOLON, PBTN_MA2 },\r
102 { KEY_APOSTROPHE, PBTN_MA3 },\r
103 { KEY_BACKSLASH, PBTN_MENU },\r
104 { KEY_LEFTBRACE, PBTN_L },\r
105 { KEY_RIGHTBRACE, PBTN_R },\r
106};\r
107\r
108static const struct in_pdata pandora_evdev_pdata = {\r
109 .defbinds = in_evdev_defbinds,\r
110 .key_map = key_pbtn_map,\r
111 .kmap_size = sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]),\r
112};\r
113\r
c7eb229a 114void pemu_prep_defconfig(void)\r
115{\r
116 defaultConfig.EmuOpt |= EOPT_VSYNC|EOPT_16BPP;\r
92dfd9af 117 defaultConfig.s_PicoOpt |= POPT_EN_MCD_GFX;\r
c7eb229a 118 defaultConfig.scaling = SCALE_2x2_3x2;\r
119}\r
120\r
121void pemu_validate_config(void)\r
122{\r
d4d62665 123 currentConfig.CPUclock = plat_target_cpu_clock_get();\r
c7eb229a 124}\r
125\r
c7eb229a 126static void draw_cd_leds(void)\r
127{\r
128 int old_reg;\r
129 old_reg = Pico_mcd->s68k_regs[0];\r
130\r
dca20eff 131 // 16-bit modes\r
132 unsigned int *p = (unsigned int *)((short *)g_screen_ptr + g_screen_width*2+4);\r
133 unsigned int col_g = (old_reg & 2) ? 0x06000600 : 0;\r
134 unsigned int col_r = (old_reg & 1) ? 0xc000c000 : 0;\r
135 *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2;\r
136 *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2;\r
137 *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r;\r
138}\r
139\r
140static void draw_pico_ptr(void)\r
141{\r
c87e36d7 142 int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000;\r
143 int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000);\r
dca20eff 144 int x = pico_pen_x, y = pico_pen_y, pitch = g_screen_ppitch;\r
145 unsigned short *p = (unsigned short *)g_screen_ptr;\r
15cc45c0 146 // storyware pages are actually squished, 2:1\r
147 int h = (pico_inp_mode == 1 ? 160 : saved_line_count);\r
148 if (h < 224) y++;\r
dca20eff 149\r
15cc45c0 150 x = (x * saved_col_count * ((1ULL<<32) / 320 + 1)) >> 32;\r
151 y = (y * h * ((1ULL<<32) / 224 + 1)) >> 32;\r
dca20eff 152 p += (saved_start_col+x) + (saved_start_line+y) * pitch;\r
153\r
15cc45c0 154 p[-pitch-1] ^= o; p[-pitch] ^= _; p[-pitch+1] ^= _; p[-pitch+2] ^= o;\r
155 p[-1] ^= _; p[0] ^= o; p[1] ^= o; p[2] ^= _;\r
156 p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= o; p[pitch+2] ^= _;\r
157 p[2*pitch-1]^= o; p[2*pitch]^= _; p[2*pitch+1]^= _; p[2*pitch+2]^= o;\r
c7eb229a 158}\r
159\r
c7eb229a 160void pemu_finalize_frame(const char *fps, const char *notice)\r
161{\r
15cc45c0 162 if (PicoIn.AHW & PAHW_PICO) {\r
163 int h = saved_line_count, w = saved_col_count;\r
164 u16 *pd = g_screen_ptr + saved_start_line*g_screen_ppitch\r
165 + saved_start_col;\r
166\r
167 if (pico_inp_mode)\r
168 emu_pico_overlay(pd, w, h, g_screen_ppitch);\r
169 if (pico_inp_mode /*== 2 || overlay*/)\r
170 draw_pico_ptr();\r
171 }\r
bf61bea0 172 if (notice && notice[0])\r
8a407398 173 emu_osd_text16(2 + g_osd_start_x, g_osd_y, notice);\r
735a987b 174 if (fps && fps[0] && (currentConfig.EmuOpt & EOPT_SHOW_FPS)) {\r
175 const char *p;\r
176 // avoid wrapping when fps is very high\r
177 if (fps[5] != ' ' && (p = strchr(fps, '/')))\r
178 fps = p;\r
179 emu_osd_text16(g_osd_fps_x, g_osd_y, fps);\r
180 }\r
93f9619e 181 if ((PicoIn.AHW & PAHW_MCD) && (currentConfig.EmuOpt & EOPT_EN_CD_LEDS))\r
c7eb229a 182 draw_cd_leds();\r
183}\r
184\r
185void plat_video_flip(void)\r
186{\r
187 g_screen_ptr = vout_fbdev_flip(layer_fb);\r
41946d70 188 PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);\r
10ef62e3 189\r
190 // XXX: drain OS event queue here, maybe we'll actually use it someday..\r
d4d62665 191 xenv_update(NULL, NULL, NULL, NULL);\r
c7eb229a 192}\r
193\r
735a987b 194// pnd doesn't use multiple renderers, but we have to handle this since it's\r
195// called on 32x enable and PicoDrawSetOutFormat() sets up the 32x layers\r
c7eb229a 196void plat_video_toggle_renderer(int change, int is_menu)\r
197{\r
735a987b 198 if (!is_menu)\r
199 PicoDrawSetOutFormat(PDF_RGB555, 0);\r
c7eb229a 200}\r
201\r
202void plat_video_menu_enter(int is_rom_loaded)\r
203{\r
204}\r
205\r
206void plat_video_menu_begin(void)\r
207{\r
c7eb229a 208}\r
209\r
210void plat_video_menu_end(void)\r
211{\r
212 g_menuscreen_ptr = vout_fbdev_flip(main_fb);\r
213}\r
214\r
d4d62665 215void plat_video_menu_leave(void)\r
216{\r
217}\r
218\r
c7eb229a 219void plat_video_wait_vsync(void)\r
220{\r
221 vout_fbdev_wait_vsync(main_fb);\r
222}\r
223\r
224void plat_status_msg_clear(void)\r
225{\r
7c18e34a 226 vout_fbdev_clear_lines(layer_fb, g_osd_y, 8);\r
c7eb229a 227}\r
228\r
229void plat_status_msg_busy_next(const char *msg)\r
230{\r
231 plat_status_msg_clear();\r
232 pemu_finalize_frame("", msg);\r
233 plat_video_flip();\r
234 emu_status_msg("");\r
235 reset_timing = 1;\r
236}\r
237\r
238void plat_status_msg_busy_first(const char *msg)\r
239{\r
240 plat_status_msg_busy_next(msg);\r
241}\r
242\r
243void plat_update_volume(int has_changed, int is_up)\r
244{\r
45285368 245}\r
c7eb229a 246\r
45285368 247void pemu_forced_frame(int no_scale, int do_emu)\r
248{\r
d40231e2 249 doing_bg_frame = 1;\r
832faed3 250 // making a copy because enabling the layer clears it's mem\r
251 emu_cmn_forced_frame(no_scale, do_emu, fb_copy);\r
d40231e2 252 doing_bg_frame = 0;\r
45285368 253\r
d4d62665 254 g_menubg_src_ptr = fb_copy;\r
c7eb229a 255}\r
256\r
257void pemu_sound_start(void)\r
258{\r
d4d62665 259 emu_sound_start();\r
c7eb229a 260}\r
261\r
262void plat_debug_cat(char *str)\r
263{\r
264}\r
265\r
266static int pnd_setup_layer_(int fd, int enabled, int x, int y, int w, int h)\r
267{\r
268 struct omapfb_plane_info pi;\r
269 struct omapfb_mem_info mi;\r
55d7dcb2 270 int is_enabled;\r
271 int retval = 0;\r
c7eb229a 272 int ret;\r
273\r
274 ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);\r
275 if (ret != 0) {\r
276 perror("QUERY_PLANE");\r
277 return -1;\r
278 }\r
279\r
280 ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);\r
281 if (ret != 0) {\r
282 perror("QUERY_MEM");\r
283 return -1;\r
284 }\r
285\r
286 /* must disable when changing stuff */\r
55d7dcb2 287 is_enabled = pi.enabled;\r
288 if (is_enabled) {\r
c7eb229a 289 pi.enabled = 0;\r
290 ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);\r
291 if (ret != 0)\r
292 perror("SETUP_PLANE");\r
55d7dcb2 293 else\r
294 is_enabled = 0;\r
c7eb229a 295 }\r
296\r
55d7dcb2 297 if (mi.size < LAYER_MEM_SIZE) {\r
298 unsigned int size_old = mi.size;\r
299\r
300 mi.size = LAYER_MEM_SIZE;\r
301 ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);\r
302 if (ret != 0) {\r
303 perror("SETUP_MEM");\r
304 fprintf(stderr, "(requested %u, had %u)\n",\r
305 mi.size, size_old);\r
306 return -1;\r
307 }\r
c7eb229a 308 }\r
309\r
310 pi.pos_x = x;\r
311 pi.pos_y = y;\r
312 pi.out_width = w;\r
313 pi.out_height = h;\r
314 pi.enabled = enabled;\r
315\r
316 ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);\r
55d7dcb2 317 if (ret == 0) {\r
318 is_enabled = pi.enabled;\r
319 }\r
320 else {\r
c7eb229a 321 perror("SETUP_PLANE");\r
55d7dcb2 322 retval = -1;\r
c7eb229a 323 }\r
324\r
55d7dcb2 325 plat_target_switch_layer(1, is_enabled);\r
326\r
327 return retval;\r
c7eb229a 328}\r
329\r
330int pnd_setup_layer(int enabled, int x, int y, int w, int h)\r
331{\r
ca980e1b 332 // it's not allowed for the layer to be partially offscreen,\r
333 // instead it is faked by emu_video_mode_change()\r
334 if (x < 0) { w += x; x = 0; }\r
335 if (y < 0) { h += y; y = 0; }\r
336 if (x + w > 800) w = 800 - x;\r
337 if (y + h > 480) h = 480 - y;\r
338\r
c7eb229a 339 return pnd_setup_layer_(vout_fbdev_get_fd(layer_fb), enabled, x, y, w, h);\r
340}\r
341\r
342void pnd_restore_layer_data(void)\r
343{\r
739e1043 344 short *t = (short *)fb_copy + 320*240 / 2 + 160;\r
c7eb229a 345\r
346 // right now this is used by menu, which wants to preview something\r
347 // so try to get something on the layer.\r
348 if ((t[0] | t[5] | t[13]) == 0)\r
349 memset32((void *)fb_copy, 0x07000700, sizeof(fb_copy) / 4);\r
350\r
d4d62665 351 memcpy(g_screen_ptr, (void *)fb_copy, 320*240*2);\r
c7eb229a 352 plat_video_flip();\r
353}\r
354\r
d5d17782 355void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)\r
c7eb229a 356{\r
ca980e1b 357 int fb_w, fb_h = 240, fb_left = 0, fb_right = 0, fb_top = 0, fb_bottom = 0;\r
c7eb229a 358\r
d40231e2 359 if (doing_bg_frame)\r
360 return;\r
361\r
c7eb229a 362 switch (currentConfig.scaling) {\r
363 case SCALE_1x1:\r
ca980e1b 364 g_layer_w = col_count;\r
c7eb229a 365 g_layer_h = fb_h;\r
366 break;\r
367 case SCALE_2x2_3x2:\r
ca980e1b 368 g_layer_w = col_count * (col_count < 320 ? 3 : 2);\r
c7eb229a 369 g_layer_h = fb_h * 2;\r
370 break;\r
371 case SCALE_2x2_2x2:\r
ca980e1b 372 g_layer_w = col_count * 2;\r
c7eb229a 373 g_layer_h = fb_h * 2;\r
374 break;\r
375 case SCALE_FULLSCREEN:\r
376 g_layer_w = 800;\r
377 g_layer_h = 480;\r
378 break;\r
379 case SCALE_CUSTOM:\r
380 g_layer_x = g_layer_cx;\r
381 g_layer_y = g_layer_cy;\r
382 g_layer_w = g_layer_cw;\r
383 g_layer_h = g_layer_ch;\r
384 break;\r
385 }\r
386\r
387 if (currentConfig.scaling != SCALE_CUSTOM) {\r
388 // center the layer\r
389 g_layer_x = 800 / 2 - g_layer_w / 2;\r
390 g_layer_y = 480 / 2 - g_layer_h / 2;\r
391 }\r
392\r
393 switch (currentConfig.scaling) {\r
394 case SCALE_FULLSCREEN:\r
395 case SCALE_CUSTOM:\r
396 fb_top = start_line;\r
ca980e1b 397 fb_h = start_line + line_count;\r
c7eb229a 398 break;\r
399 }\r
ca980e1b 400 fb_w = 320;\r
401 fb_left = start_col;\r
402 fb_right = 320 - (start_col + col_count);\r
403 if (currentConfig.scaling == SCALE_CUSTOM) {\r
404 int right = g_layer_x + g_layer_w;\r
405 int bottom = g_layer_y + g_layer_h;\r
406 if (g_layer_x < 0)\r
407 fb_left += -g_layer_x * col_count / g_menuscreen_w;\r
408 if (g_layer_y < 0)\r
409 fb_top += -g_layer_y * line_count / g_menuscreen_h;\r
410 if (right > g_menuscreen_w)\r
411 fb_right += (right - g_menuscreen_w) * col_count / g_menuscreen_w;\r
412 if (bottom > g_menuscreen_h)\r
413 fb_bottom += (bottom - g_menuscreen_h) * line_count / g_menuscreen_h;\r
414 }\r
415 fb_w -= fb_left + fb_right;\r
416 fb_h -= fb_top + fb_bottom;\r
c7eb229a 417\r
418 pnd_setup_layer(1, g_layer_x, g_layer_y, g_layer_w, g_layer_h);\r
f20ad523 419 vout_fbdev_resize(layer_fb, fb_w, fb_h, 16, fb_left, fb_right, fb_top, fb_bottom, 4, 0);\r
c7eb229a 420 vout_fbdev_clear(layer_fb);\r
bf61bea0 421 plat_video_flip();\r
ca980e1b 422\r
423 g_osd_start_x = start_col;\r
424 g_osd_fps_x = start_col + col_count - 5*8 - 2;\r
425 g_osd_y = fb_top + fb_h - 8;\r
426\r
427 saved_start_line = start_line, saved_line_count = line_count;\r
428 saved_start_col = start_col, saved_col_count = col_count;\r
c7eb229a 429}\r
430\r
d4d62665 431void plat_video_loop_prepare(void)\r
c7eb229a 432{\r
c7eb229a 433 // make sure there is no junk left behind the layer\r
d4d62665 434 memset(g_menuscreen_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2);\r
c7eb229a 435 g_menuscreen_ptr = vout_fbdev_flip(main_fb);\r
436\r
92efe29e 437 PicoDrawSetOutFormat(PDF_RGB555, 0);\r
c7eb229a 438 // emu_video_mode_change will call pnd_setup_layer()\r
d4d62665 439}\r
c7eb229a 440\r
d4d62665 441void pemu_loop_prep(void)\r
442{\r
c7eb229a 443 // dirty buffers better go now than during gameplay\r
d9653efd 444 fflush(stdout);\r
445 fflush(stderr);\r
c7eb229a 446 sync();\r
447 sleep(0);\r
c7eb229a 448}\r
449\r
450void pemu_loop_end(void)\r
451{\r
8a407398 452 memset(fb_copy, 0, sizeof(fb_copy));\r
c7eb229a 453 /* do one more frame for menu bg */\r
45285368 454 pemu_forced_frame(0, 1);\r
c7eb229a 455\r
456 pnd_setup_layer(0, g_layer_x, g_layer_y, g_layer_w, g_layer_h);\r
c7eb229a 457}\r
458\r
459void plat_wait_till_us(unsigned int us_to)\r
460{\r
461 unsigned int now;\r
462 signed int diff;\r
463\r
464 now = plat_get_ticks_us();\r
465\r
466 // XXX: need to check NOHZ\r
467 diff = (signed int)(us_to - now);\r
468 if (diff > 10000) {\r
469 //printf("sleep %d\n", us_to - now);\r
470 usleep(diff * 15 / 16);\r
471 now = plat_get_ticks_us();\r
472 //printf(" wake %d\n", (signed)(us_to - now));\r
473 }\r
474/*\r
475 while ((signed int)(us_to - now) > 512) {\r
476 spend_cycles(1024);\r
477 now = plat_get_ticks_us();\r
478 }\r
479*/\r
480}\r
481\r
759c9d38 482void *plat_mem_get_for_drc(size_t size)\r
483{\r
484 return NULL;\r
485}\r
486\r
58fc34b1 487int plat_parse_arg(int argc, char *argv[], int *x)\r
488{\r
489 return 1;\r
490}\r
491\r
c7eb229a 492void plat_early_init(void)\r
493{\r
494}\r
495\r
496void plat_init(void)\r
497{\r
498 const char *main_fb_name, *layer_fb_name;\r
499 int fd, ret, w, h;\r
500\r
501 main_fb_name = getenv("FBDEV_MAIN");\r
502 if (main_fb_name == NULL)\r
503 main_fb_name = "/dev/fb0";\r
504\r
505 layer_fb_name = getenv("FBDEV_LAYER");\r
506 if (layer_fb_name == NULL)\r
507 layer_fb_name = "/dev/fb1";\r
508\r
509 // must set the layer up first to be able to use it\r
510 fd = open(layer_fb_name, O_RDWR);\r
511 if (fd == -1) {\r
512 fprintf(stderr, "%s: ", layer_fb_name);\r
513 perror("open");\r
514 exit(1);\r
515 }\r
516\r
517 ret = pnd_setup_layer_(fd, 0, g_layer_x, g_layer_y, g_layer_w, g_layer_h);\r
518 close(fd);\r
519 if (ret != 0) {\r
520 fprintf(stderr, "failed to set up layer, exiting.\n");\r
521 exit(1);\r
522 }\r
523\r
d4d62665 524 xenv_init(NULL, "PicoDrive " VERSION);\r
c7eb229a 525\r
526 w = h = 0;\r
21ebcfd3 527 main_fb = vout_fbdev_init(main_fb_name, &w, &h, 16, 2);\r
c7eb229a 528 if (main_fb == NULL) {\r
529 fprintf(stderr, "couldn't init fb: %s\n", main_fb_name);\r
530 exit(1);\r
531 }\r
532\r
9cdfc191 533 g_menuscreen_w = g_menuscreen_pp = w;\r
d40231e2 534 g_menuscreen_h = h;\r
c7eb229a 535 g_menuscreen_ptr = vout_fbdev_flip(main_fb);\r
536\r
537 w = 320; h = 240;\r
b011c2af 538 layer_fb = vout_fbdev_init(layer_fb_name, &w, &h, 16, 4);\r
c7eb229a 539 if (layer_fb == NULL) {\r
540 fprintf(stderr, "couldn't init fb: %s\n", layer_fb_name);\r
541 goto fail0;\r
542 }\r
543\r
544 if (w != g_screen_width || h != g_screen_height) {\r
545 fprintf(stderr, "%dx%d not supported on %s\n", w, h, layer_fb_name);\r
546 goto fail1;\r
547 }\r
548 g_screen_ptr = vout_fbdev_flip(layer_fb);\r
549\r
d40231e2 550 temp_frame = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1);\r
551 if (temp_frame == NULL) {\r
552 fprintf(stderr, "OOM\n");\r
553 goto fail1;\r
554 }\r
c7eb229a 555 g_menubg_ptr = temp_frame;\r
556 g_menubg_src_ptr = temp_frame;\r
557\r
c7eb229a 558 pnd_menu_init();\r
45285368 559\r
55d7dcb2 560 // default ROM path\r
561 strcpy(rom_fname_loaded, "/media");\r
562\r
4e3551a5 563 in_evdev_init(&pandora_evdev_pdata);\r
d4d62665 564 in_probe();\r
565 plat_target_setup_input();\r
566\r
567 sndout_oss_frag_frames = 2;\r
568\r
c7eb229a 569 return;\r
570\r
571fail1:\r
572 vout_fbdev_finish(layer_fb);\r
573fail0:\r
574 vout_fbdev_finish(main_fb);\r
575 exit(1);\r
576}\r
577\r
578void plat_finish(void)\r
579{\r
c7eb229a 580 vout_fbdev_finish(main_fb);\r
10ef62e3 581 xenv_finish();\r
c7eb229a 582\r
583 printf("all done\n");\r
584}\r
585\r