initial pandora port
[fceu.git] / drivers / pandora / pandora.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <sys/ioctl.h>
8 #include <unistd.h>
9 #include <linux/input.h>
10 #include <linux/omapfb.h>
11
12 #include "../common/platform.h"
13 #include "../common/input.h"
14 #include "../common/settings.h"
15 #include "../common/main.h"
16 #include "../common/args.h"
17 #include "../../video.h"
18 #include "../arm/asmutils.h"
19 #include "../libpicofe/input.h"
20 #include "../libpicofe/plat.h"
21 #include "../libpicofe/menu.h"
22 #include "../libpicofe/linux/in_evdev.h"
23 #include "../libpicofe/linux/fbdev.h"
24 #include "../libpicofe/linux/xenv.h"
25
26 static int g_layer_x, g_layer_y, g_layer_w, g_layer_h;
27 static struct vout_fbdev *main_fb, *layer_fb;
28 static void *layer_buf;
29 static int bounce_buf[320 * 241 / 4];
30 static unsigned short pal[256];
31
32 static const struct in_default_bind in_evdev_defbinds[] = {
33   { KEY_UP,       IN_BINDTYPE_PLAYER12, NKEYB_UP },
34   { KEY_DOWN,     IN_BINDTYPE_PLAYER12, NKEYB_DOWN },
35   { KEY_LEFT,     IN_BINDTYPE_PLAYER12, NKEYB_LEFT },
36   { KEY_RIGHT,    IN_BINDTYPE_PLAYER12, NKEYB_RIGHT },
37   { KEY_PAGEDOWN, IN_BINDTYPE_PLAYER12, NKEYB_B },
38   { KEY_END,      IN_BINDTYPE_PLAYER12, NKEYB_A },
39   { KEY_HOME,     IN_BINDTYPE_PLAYER12, NKEYB_B_TURBO },
40   { KEY_PAGEUP,   IN_BINDTYPE_PLAYER12, NKEYB_A_TURBO },
41   { KEY_LEFTCTRL, IN_BINDTYPE_PLAYER12, NKEYB_SELECT },
42   { KEY_LEFTALT,  IN_BINDTYPE_PLAYER12, NKEYB_START },
43   { KEY_SPACE,    IN_BINDTYPE_EMU, EACTB_ENTER_MENU },
44   { 0, 0, 0 }
45 };
46
47 static int omap_setup_layer_(int fd, int enabled, int x, int y, int w, int h)
48 {
49         struct omapfb_plane_info pi = { 0, };
50         struct omapfb_mem_info mi = { 0, };
51         int ret;
52
53         ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);
54         if (ret != 0) {
55                 perror("QUERY_PLANE");
56                 return -1;
57         }
58
59         ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);
60         if (ret != 0) {
61                 perror("QUERY_MEM");
62                 return -1;
63         }
64
65         /* must disable when changing stuff */
66         if (pi.enabled) {
67                 pi.enabled = 0;
68                 ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
69                 if (ret != 0)
70                         perror("SETUP_PLANE");
71         }
72
73         if (mi.size < 640*512*3*3) {
74                 mi.size = 640*512*3*3;
75                 ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
76                 if (ret != 0) {
77                         perror("SETUP_MEM");
78                         return -1;
79                 }
80         }
81
82         pi.pos_x = x;
83         pi.pos_y = y;
84         pi.out_width = w;
85         pi.out_height = h;
86         pi.enabled = enabled;
87
88         ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
89         if (ret != 0) {
90                 perror("SETUP_PLANE");
91                 return -1;
92         }
93
94         return 0;
95 }
96
97 static int omap_enable_layer(int enabled)
98 {
99         return omap_setup_layer_(vout_fbdev_get_fd(layer_fb), enabled,
100                 g_layer_x, g_layer_y, g_layer_w, g_layer_h);
101 }
102
103 void platform_init(void)
104 {
105         const char *main_fb_name, *layer_fb_name;
106         int fd, ret, w, h;
107
108         memset(&Settings, 0, sizeof(Settings));
109         Settings.frameskip = 0;
110         Settings.sound_rate = 44100;
111         Settings.turbo_rate_add = (8*2 << 24) / 60 + 1; // 8Hz turbofire
112         Settings.gamma = 100;
113         Settings.sstate_confirm = 1;
114
115         main_fb_name = getenv("FBDEV_MAIN");
116         if (main_fb_name == NULL)
117                 main_fb_name = "/dev/fb0";
118
119         layer_fb_name = getenv("FBDEV_LAYER");
120         if (layer_fb_name == NULL)
121                 layer_fb_name = "/dev/fb1";
122
123         // must set the layer up first to be able to use it
124         fd = open(layer_fb_name, O_RDWR);
125         if (fd == -1) {
126                 fprintf(stderr, "%s: ", layer_fb_name);
127                 perror("open");
128                 exit(1);
129         }
130
131         g_layer_x = 80, g_layer_y = 0;
132         g_layer_w = 640, g_layer_h = 480;
133
134         ret = omap_setup_layer_(fd, 0, g_layer_x, g_layer_y, g_layer_w, g_layer_h);
135         close(fd);
136         if (ret != 0) {
137                 fprintf(stderr, "failed to set up layer, exiting.\n");
138                 exit(1);
139         }
140
141         xenv_init(NULL, "fceu");
142
143         w = h = 0;
144         main_fb = vout_fbdev_init(main_fb_name, &w, &h, 16, 2);
145         if (main_fb == NULL) {
146                 fprintf(stderr, "couldn't init fb: %s\n", main_fb_name);
147                 exit(1);
148         }
149
150         g_menuscreen_w = w;
151         g_menuscreen_h = h;
152         g_menuscreen_ptr = vout_fbdev_flip(main_fb);
153
154         w = 640;
155         h = 512;
156         layer_fb = vout_fbdev_init(layer_fb_name, &w, &h, 16, 3);
157         if (layer_fb == NULL) {
158                 fprintf(stderr, "couldn't init fb: %s\n", layer_fb_name);
159                 goto fail0;
160         }
161         layer_buf = vout_fbdev_resize(layer_fb, 256, 240, 16,
162                 0, 0, 0, 0, 3);
163         if (layer_buf == NULL) {
164                 fprintf(stderr, "couldn't get layer buf\n");
165                 goto fail1;
166         }
167
168         plat_target_init();
169         omap_enable_layer(1);
170
171         XBuf = (void *)bounce_buf;
172
173         return;
174
175 fail1:
176         vout_fbdev_finish(layer_fb);
177 fail0:
178         vout_fbdev_finish(main_fb);
179         xenv_finish();
180         exit(1);
181 }
182
183 void platform_late_init(void)
184 {
185         in_evdev_init(in_evdev_defbinds);
186         in_probe();
187         plat_target_setup_input();
188 }
189
190 /* video */
191 void CleanSurface(void)
192 {
193         memset(bounce_buf, 0, sizeof(bounce_buf));
194         vout_fbdev_clear(layer_fb);
195 }
196
197 void KillVideo(void)
198 {
199 }
200
201 int InitVideo(void)
202 {
203         CleanSurface();
204
205         srendline = 0;
206         erendline = 239;
207
208         return 1;
209 }
210
211 // 16: rrrr rggg gg0b bbbb
212 void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b)
213 {
214         pal[index] = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
215 }
216
217 void FCEUD_GetPalette(uint8 index, uint8 *r, uint8 *g, uint8 *b)
218 {
219         unsigned int v = pal[index];
220         *r = (v >> 8) & 0xf8;
221         *g = (v >> 3) & 0xfc;
222         *b = v << 3;
223 }
224
225 void BlitPrepare(int skip)
226 {
227         if (skip)
228                 return;
229
230         if (eoptions & EO_CLIPSIDES)
231         {
232                 int i, *p = bounce_buf + 32/4;
233                 for (i = 240; i; i--, p += 320/4)
234                 {
235                         p[0] = p[1] = p[62] = p[63] = 0;
236                 }
237         }
238
239         if (Settings.accurate_mode)
240         {
241                 int i, *p = bounce_buf + 32/4;
242                 if (srendline > 0)
243                         for (i = srendline; i > 0; i--, p += 320/4)
244                                 memset(p, 0, 256);
245                 if (erendline < 239)
246                 {
247                         int *p = bounce_buf + erendline*320/4 + 32/4;
248                         for (i = 239-srendline; i > 0; i--, p += 320/4)
249                                 memset(p, 0, 256);
250                 }
251         }
252 }
253
254 void BlitScreen(int skip)
255 {
256         char *s = (char *)bounce_buf + 32;
257         short *d = (short *)layer_buf;
258         int i;
259
260         if (skip)
261                 return;
262
263         for (i = 0; i < 239; i++, d += 256, s += 320)
264                 do_clut(d, s, pal, 256);
265         
266         layer_buf = vout_fbdev_flip(layer_fb);
267 }
268
269 void platform_apply_config(void)
270 {
271 }
272
273 void platform_set_volume(int val)
274 {
275 }
276
277 void plat_video_menu_enter(int is_rom_loaded)
278 {
279         omap_enable_layer(0);
280 }
281
282 void plat_video_menu_begin(void)
283 {
284 }
285
286 void plat_video_menu_end(void)
287 {
288         g_menuscreen_ptr = vout_fbdev_flip(main_fb);
289 }
290
291 void plat_video_menu_leave(void)
292 {
293         memset(g_menuscreen_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2);
294         g_menuscreen_ptr = vout_fbdev_flip(main_fb);
295
296         omap_enable_layer(1);
297 }
298
299 char *DriverUsage="";
300
301 ARGPSTRUCT DriverArgs[]={
302          {0,0,0,0}
303 };
304
305 void DoDriverArgs(void)
306 {
307 }
308
309 void GetBaseDirectory(char *BaseDirectory)
310 {
311         strcpy(BaseDirectory, "fceultra");
312 }
313
314 void platform_finish(void)
315 {
316         omap_enable_layer(0);
317         vout_fbdev_finish(layer_fb);
318         vout_fbdev_finish(main_fb);
319         xenv_finish();
320 }