9819df8f68f49295fd09756665424d4c31af8f81
[gpsp.git] / pandora / pnd.c
1 /* gameplaySP - pandora backend
2  *
3  * Copyright (C) 2011 notaz <notasas@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19
20 #include "../common.h"
21 #include <X11/keysym.h>
22 #include "linux/omapfb.h" //
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <sys/ioctl.h>
27
28 #include "linux/fbdev.h"
29 #include "linux/xenv.h"
30
31 enum gpsp_key {
32   GKEY_UP       = 1 << 0,
33   GKEY_LEFT     = 1 << 1,
34   GKEY_DOWN     = 1 << 2,
35   GKEY_RIGHT    = 1 << 3,
36   GKEY_START    = 1 << 4,
37   GKEY_SELECT   = 1 << 5,
38   GKEY_L        = 1 << 6,
39   GKEY_R        = 1 << 7,
40   GKEY_A        = 1 << 8,
41   GKEY_B        = 1 << 9,
42   GKEY_X        = 1 << 10,
43   GKEY_Y        = 1 << 11,
44   GKEY_1        = 1 << 12,
45   GKEY_2        = 1 << 13,
46   GKEY_3        = 1 << 14,
47   GKEY_4        = 1 << 15,
48   GKEY_MENU     = 1 << 16,
49 };
50
51 u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT] =
52 {
53   GKEY_UP,
54   GKEY_LEFT,
55   GKEY_DOWN,
56   GKEY_RIGHT,
57   GKEY_START,
58   GKEY_SELECT,
59   GKEY_L,
60   GKEY_R,
61   GKEY_A,
62   GKEY_B,
63   GKEY_X,
64   GKEY_Y,
65   GKEY_1,
66   GKEY_2,
67   GKEY_3,
68   GKEY_4,
69   GKEY_MENU,
70 };
71
72 u32 gamepad_config_map[PLAT_BUTTON_COUNT] =
73 {
74   BUTTON_ID_UP,                 // Up
75   BUTTON_ID_LEFT,               // Left
76   BUTTON_ID_DOWN,               // Down
77   BUTTON_ID_RIGHT,              // Right
78   BUTTON_ID_START,              // Start
79   BUTTON_ID_SELECT,             // Select
80   BUTTON_ID_L,                  // Ltrigger
81   BUTTON_ID_R,                  // Rtrigger
82   BUTTON_ID_FPS,                // A
83   BUTTON_ID_A,                  // B
84   BUTTON_ID_B,                  // X
85   BUTTON_ID_MENU,               // Y
86   BUTTON_ID_SAVESTATE,          // 1
87   BUTTON_ID_LOADSTATE,          // 2
88   BUTTON_ID_FASTFORWARD,        // 3
89   BUTTON_ID_NONE,               // 4
90   BUTTON_ID_MENU                // Space
91 };
92
93 static const u32 xk_to_gkey[] = {
94   XK_Up, XK_Left, XK_Down, XK_Right, XK_Alt_L, XK_Control_L,
95   XK_Shift_R, XK_Control_R, XK_Home, XK_End, XK_Page_Down, XK_Page_Up,
96   XK_1, XK_2, XK_3, XK_4, XK_space,
97 };
98
99 static const u8 gkey_to_cursor[32] = {
100   [0 ... 31] = CURSOR_NONE,
101   [0] = CURSOR_UP, CURSOR_LEFT, CURSOR_DOWN, CURSOR_RIGHT, CURSOR_NONE, CURSOR_NONE,
102   CURSOR_L, CURSOR_R, CURSOR_SELECT, CURSOR_SELECT, CURSOR_EXIT, CURSOR_BACK,
103 };
104
105 struct vout_fbdev *fb;
106
107 static int omap_setup_layer(int fd, int enabled, int x, int y, int w, int h)
108 {
109   struct omapfb_plane_info pi = { 0, };
110   struct omapfb_mem_info mi = { 0, };
111   int ret;
112
113   ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);
114   if (ret != 0) {
115     perror("QUERY_PLANE");
116     return -1;
117   }
118
119   ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);
120   if (ret != 0) {
121     perror("QUERY_MEM");
122     return -1;
123   }
124
125   /* must disable when changing stuff */
126   if (pi.enabled) {
127     pi.enabled = 0;
128     ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
129     if (ret != 0)
130       perror("SETUP_PLANE");
131   }
132
133   if (mi.size < 240*160*2*4) {
134     mi.size = 240*160*2*4;
135     ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
136     if (ret != 0) {
137       perror("SETUP_MEM");
138       return -1;
139     }
140   }
141
142   pi.pos_x = x;
143   pi.pos_y = y;
144   pi.out_width = w;
145   pi.out_height = h;
146   pi.enabled = enabled;
147
148   ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
149   if (ret != 0) {
150     perror("SETUP_PLANE");
151     return -1;
152   }
153
154   return 0;
155 }
156
157 void gpsp_plat_init(void)
158 {
159   int ret, w, h, fd;
160   const char *layer_fb_name;
161
162   ret = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);
163   if (ret != 0) {
164     fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
165     exit(1);
166   }
167
168   layer_fb_name = getenv("FBDEV_LAYER");
169   if (layer_fb_name == NULL)
170     layer_fb_name = "/dev/fb1";
171
172   ret = xenv_init();
173   if (ret != 0) {
174     fprintf(stderr, "xenv_init failed with %d\n", ret);
175     exit(1);
176   }
177
178   // must set the layer up first to be able to use it
179   fd = open(layer_fb_name, O_RDWR);
180   if (fd == -1) {
181     fprintf(stderr, "%s: ", layer_fb_name);
182     perror("open");
183     exit(1);
184   }
185
186   ret = omap_setup_layer(fd, 0, 0, 0, 400, 272);
187   close(fd);
188   if (ret != 0) {
189     fprintf(stderr, "failed to set up layer, exiting.\n");
190     exit(1);
191   }
192
193   w = 240;
194   h = 160;
195   fb = vout_fbdev_init("/dev/fb1", &w, &h, 16, 4);
196   if (fb == NULL) {
197     fprintf(stderr, "vout_fbdev_init failed\n");
198     exit(1);
199   }
200
201   // default to 3x scale
202   screen_scale = 2;
203 }
204
205 void gpsp_plat_quit(void)
206 {
207   xenv_finish();
208   omap_setup_layer(vout_fbdev_get_fd(fb), 0, 0, 0, 0, 0);
209   vout_fbdev_finish(fb);
210   SDL_Quit();
211 }
212
213 u32 gpsp_plat_joystick_read(void)
214 {
215   static int gkeystate;
216   int key, is_down, i;
217   int gkey = -1;
218   
219   key = xenv_update(&is_down);
220   for (i = 0; i < sizeof(xk_to_gkey) / sizeof(xk_to_gkey[0]); i++) {
221     if (key == xk_to_gkey[i]) {
222       gkey = i;
223       break;
224     }
225   }
226
227   if (gkey >= 0) {
228     if (is_down)
229       gkeystate |= 1 << gkey;
230     else
231       gkeystate &= ~(1 << gkey);
232   }
233   
234   return gkeystate;
235 }
236
237 u32 gpsp_plat_buttons_to_cursor(u32 buttons)
238 {
239   int i;
240
241   if (buttons == 0)
242     return CURSOR_NONE;
243
244   for (i = 0; (buttons & 1) == 0; i++, buttons >>= 1)
245     ;
246
247   return gkey_to_cursor[i];
248 }
249
250 static void set_filter(int is_filtered)
251 {
252   static int was_filtered = -1;
253   char buf[128];
254
255   if (is_filtered == was_filtered)
256     return;
257
258   snprintf(buf, sizeof(buf), "sudo -n /usr/pandora/scripts/op_videofir.sh %s",
259     is_filtered ? "default" : "none");
260   system(buf);
261   was_filtered = is_filtered;
262 }
263
264 void *fb_flip_screen(void)
265 {
266   return vout_fbdev_flip(fb);
267 }
268
269 void fb_wait_vsync(void)
270 {
271   vout_fbdev_wait_vsync(fb);
272 }
273
274 void fb_set_mode(int w, int h, int buffers, int scale, int filter)
275 {
276   int lx, ly, lw = w, lh = h;
277   switch (scale) {
278     case 0:
279       lw = w;
280       lh = h;
281       break;
282     case 1:
283       lw = w * 2;
284       lh = h * 2;
285       break;
286     case 2:
287       lw = w * 3;
288       lh = h * 3;
289       break;
290     case 3:
291       lw = 800;
292       lh = 480;
293       break;
294     case 15:
295       lw = w * 2;
296       lh = h + h /2;
297       break;
298     default:
299       fprintf(stderr, "unknown scale: %d\n", scale);
300       break;
301   }
302   if (lw > 800)
303     lw = 800;
304   if (lh > 480)
305     lh = 480;
306   lx = 800 / 2 - lw / 2;
307   ly = 480 / 2 - lh / 2;
308
309   omap_setup_layer(vout_fbdev_get_fd(fb), 1, lx, ly, lw, lh);
310   set_filter(filter);
311
312   vout_fbdev_resize(fb, w, h, 16, 0, 0, 0, 0, buffers);
313 }
314
315 // vim:shiftwidth=2:expandtab