/* gameplaySP - pandora backend * * Copyright (C) 2011 notaz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "../common.h" #include #include "linux/omapfb.h" // #include #include #include #include #include "linux/fbdev.h" #include "linux/xenv.h" enum gpsp_key { GKEY_UP = 1 << 0, GKEY_LEFT = 1 << 1, GKEY_DOWN = 1 << 2, GKEY_RIGHT = 1 << 3, GKEY_START = 1 << 4, GKEY_SELECT = 1 << 5, GKEY_L = 1 << 6, GKEY_R = 1 << 7, GKEY_A = 1 << 8, GKEY_B = 1 << 9, GKEY_X = 1 << 10, GKEY_Y = 1 << 11, GKEY_1 = 1 << 12, GKEY_2 = 1 << 13, GKEY_3 = 1 << 14, GKEY_4 = 1 << 15, GKEY_MENU = 1 << 16, }; u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT] = { GKEY_UP, GKEY_LEFT, GKEY_DOWN, GKEY_RIGHT, GKEY_START, GKEY_SELECT, GKEY_L, GKEY_R, GKEY_A, GKEY_B, GKEY_X, GKEY_Y, GKEY_1, GKEY_2, GKEY_3, GKEY_4, GKEY_MENU, }; u32 gamepad_config_map[PLAT_BUTTON_COUNT] = { BUTTON_ID_UP, // Up BUTTON_ID_LEFT, // Left BUTTON_ID_DOWN, // Down BUTTON_ID_RIGHT, // Right BUTTON_ID_START, // Start BUTTON_ID_SELECT, // Select BUTTON_ID_L, // Ltrigger BUTTON_ID_R, // Rtrigger BUTTON_ID_FPS, // A BUTTON_ID_A, // B BUTTON_ID_B, // X BUTTON_ID_MENU, // Y BUTTON_ID_SAVESTATE, // 1 BUTTON_ID_LOADSTATE, // 2 BUTTON_ID_FASTFORWARD, // 3 BUTTON_ID_NONE, // 4 BUTTON_ID_MENU // Space }; static const u32 xk_to_gkey[] = { XK_Up, XK_Left, XK_Down, XK_Right, XK_Alt_L, XK_Control_L, XK_Shift_R, XK_Control_R, XK_Home, XK_End, XK_Page_Down, XK_Page_Up, XK_1, XK_2, XK_3, XK_4, XK_space, }; static const u8 gkey_to_cursor[32] = { [0 ... 31] = CURSOR_NONE, [0] = CURSOR_UP, CURSOR_LEFT, CURSOR_DOWN, CURSOR_RIGHT, CURSOR_NONE, CURSOR_NONE, CURSOR_L, CURSOR_R, CURSOR_SELECT, CURSOR_SELECT, CURSOR_EXIT, CURSOR_BACK, }; struct vout_fbdev *fb; static int omap_setup_layer(int fd, int enabled, int x, int y, int w, int h, int first_call) { struct omapfb_plane_info pi = { 0, }; struct omapfb_mem_info mi = { 0, }; int ret; ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi); if (ret != 0) { perror("QUERY_PLANE"); return -1; } ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi); if (ret != 0) { perror("QUERY_MEM"); return -1; } /* must disable when changing stuff */ if (pi.enabled) { pi.enabled = 0; ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); if (ret != 0) perror("SETUP_PLANE"); } if (first_call) { mi.size = 640*512*3*3; ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi); if (ret != 0) { perror("SETUP_MEM"); return -1; } } pi.pos_x = x; pi.pos_y = y; pi.out_width = w; pi.out_height = h; pi.enabled = enabled; ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); if (ret != 0) { perror("SETUP_PLANE"); return -1; } return 0; } void gpsp_plat_init(void) { int ret, w, h, fd; const char *layer_fb_name; ret = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE); if (ret != 0) { fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); exit(1); } layer_fb_name = getenv("FBDEV_LAYER"); if (layer_fb_name == NULL) layer_fb_name = "/dev/fb1"; ret = xenv_init(); if (ret != 0) { fprintf(stderr, "xenv_init failed with %d\n", ret); exit(1); } // must set the layer up first to be able to use it fd = open(layer_fb_name, O_RDWR); if (fd == -1) { fprintf(stderr, "%s: ", layer_fb_name); perror("open"); exit(1); } ret = omap_setup_layer(fd, 0, 0, 0, 400, 272, 1); close(fd); if (ret != 0) { fprintf(stderr, "failed to set up layer, exiting.\n"); exit(1); } w = 240; h = 160; fb = vout_fbdev_init("/dev/fb1", &w, &h, 16, 4); if (fb == NULL) { fprintf(stderr, "vout_fbdev_init failed\n"); exit(1); } // default to 3x scale screen_scale = 2; } void gpsp_plat_quit(void) { xenv_finish(); omap_setup_layer(vout_fbdev_get_fd(fb), 0, 0, 0, 0, 0, 0); vout_fbdev_finish(fb); SDL_Quit(); } u32 gpsp_plat_joystick_read(void) { static int gkeystate; int key, is_down, i; int gkey = -1; key = xenv_update(&is_down); for (i = 0; i < sizeof(xk_to_gkey) / sizeof(xk_to_gkey[0]); i++) { if (key == xk_to_gkey[i]) { gkey = i; break; } } if (gkey >= 0) { if (is_down) gkeystate |= 1 << gkey; else gkeystate &= ~(1 << gkey); } return gkeystate; } u32 gpsp_plat_buttons_to_cursor(u32 buttons) { int i; if (buttons == 0) return CURSOR_NONE; for (i = 0; (buttons & 1) == 0; i++, buttons >>= 1) ; return gkey_to_cursor[i]; } static void set_filter(int is_filtered) { static int was_filtered = -1; char buf[128]; if (is_filtered == was_filtered) return; snprintf(buf, sizeof(buf), "sudo -n /usr/pandora/scripts/op_videofir.sh %s", is_filtered ? "default" : "none"); system(buf); was_filtered = is_filtered; } void *fb_flip_screen(void) { return vout_fbdev_flip(fb); } void fb_wait_vsync(void) { vout_fbdev_wait_vsync(fb); } void fb_set_mode(int w, int h, int buffers, int scale, int filter) { int lx, ly, lw = w, lh = h; switch (scale) { case 0: lw = w; lh = h; break; case 1: lw = w * 2; lh = h * 2; break; case 2: lw = w * 3; lh = h * 3; break; case 3: lw = 800; lh = 480; break; case 15: lw = w * 2; lh = h + h /2; break; default: fprintf(stderr, "unknown scale: %d\n", scale); break; } if (lw > 800) lw = 800; if (lh > 480) lh = 480; lx = 800 / 2 - lw / 2; ly = 480 / 2 - lh / 2; omap_setup_layer(vout_fbdev_get_fd(fb), 1, lx, ly, lw, lh, 0); set_filter(filter); vout_fbdev_resize(fb, w, h, 16, 0, 0, 0, 0, buffers); } // vim:shiftwidth=2:expandtab