321a4b677ce0ae73930c180e142b73125fa33bc6
[libpicofe.git] / gp2x / plat.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "plat_gp2x.h"
6 #include "soc.h"
7 #include "warm.h"
8 #include "../common/plat.h"
9 #include "../common/readpng.h"
10 #include "../common/menu.h"
11 #include "../common/emu.h"
12 #include "../common/input.h"
13 #include "../linux/sndout_oss.h"
14
15 #include <pico/pico.h>
16
17 /* GP2X local */
18 int default_cpu_clock;
19 int gp2x_dev_id;
20 int gp2x_current_bpp;
21 void *gp2x_screens[4];
22
23 #include <linux/input.h>
24
25 static const char * const caanoo_keys[KEY_MAX + 1] = {
26         [0 ... KEY_MAX] = NULL,
27         [KEY_UP]        = "Up",
28         [KEY_LEFT]      = "Left",
29         [KEY_RIGHT]     = "Right",
30         [KEY_DOWN]      = "Down",
31         [BTN_TRIGGER]   = "A",
32         [BTN_THUMB]     = "X",
33         [BTN_THUMB2]    = "B",
34         [BTN_TOP]       = "Y",
35         [BTN_TOP2]      = "L",
36         [BTN_PINKIE]    = "R",
37         [BTN_BASE]      = "Home",
38         [BTN_BASE2]     = "Lock",
39         [BTN_BASE3]     = "I",
40         [BTN_BASE4]     = "II",
41         [BTN_BASE5]     = "Push",
42 };
43
44 struct in_default_bind in_evdev_defbinds[] =
45 {
46         /* MXYZ SACB RLDU */
47         { KEY_UP,       IN_BINDTYPE_PLAYER12, 0 },
48         { KEY_DOWN,     IN_BINDTYPE_PLAYER12, 1 },
49         { KEY_LEFT,     IN_BINDTYPE_PLAYER12, 2 },
50         { KEY_RIGHT,    IN_BINDTYPE_PLAYER12, 3 },
51         { KEY_S,        IN_BINDTYPE_PLAYER12, 4 },      /* B */
52         { KEY_D,        IN_BINDTYPE_PLAYER12, 5 },      /* C */
53         { KEY_A,        IN_BINDTYPE_PLAYER12, 6 },      /* A */
54         { KEY_ENTER,    IN_BINDTYPE_PLAYER12, 7 },
55         { KEY_BACKSLASH, IN_BINDTYPE_EMU, PEVB_MENU },
56         /* Caanoo */
57         { BTN_THUMB,    IN_BINDTYPE_PLAYER12, 4 },      /* B */
58         { BTN_THUMB2,   IN_BINDTYPE_PLAYER12, 5 },      /* C */
59         { BTN_TRIGGER,  IN_BINDTYPE_PLAYER12, 6 },      /* A */
60         { BTN_BASE3,    IN_BINDTYPE_PLAYER12, 7 },
61         { BTN_TOP2,     IN_BINDTYPE_EMU, PEVB_STATE_SAVE },
62         { BTN_PINKIE,   IN_BINDTYPE_EMU, PEVB_STATE_LOAD },
63         { BTN_BASE,     IN_BINDTYPE_EMU, PEVB_MENU },
64         { 0, 0, 0 }
65 };
66
67 void gp2x_video_changemode(int bpp)
68 {
69         gp2x_video_changemode_ll(bpp);
70
71         gp2x_current_bpp = bpp < 0 ? -bpp : bpp;
72 }
73
74 static void gp2x_memcpy_buffers(int buffers, void *data, int offset, int len)
75 {
76         char *dst;
77         if (buffers & (1<<0)) { dst = (char *)gp2x_screens[0] + offset; if (dst != data) memcpy(dst, data, len); }
78         if (buffers & (1<<1)) { dst = (char *)gp2x_screens[1] + offset; if (dst != data) memcpy(dst, data, len); }
79         if (buffers & (1<<2)) { dst = (char *)gp2x_screens[2] + offset; if (dst != data) memcpy(dst, data, len); }
80         if (buffers & (1<<3)) { dst = (char *)gp2x_screens[3] + offset; if (dst != data) memcpy(dst, data, len); }
81 }
82
83 void gp2x_memcpy_all_buffers(void *data, int offset, int len)
84 {
85         gp2x_memcpy_buffers(0xf, data, offset, len);
86 }
87
88 void gp2x_memset_all_buffers(int offset, int byte, int len)
89 {
90         memset((char *)gp2x_screens[0] + offset, byte, len);
91         memset((char *)gp2x_screens[1] + offset, byte, len);
92         memset((char *)gp2x_screens[2] + offset, byte, len);
93         memset((char *)gp2x_screens[3] + offset, byte, len);
94 }
95
96 void gp2x_make_fb_bufferable(int yes)
97 {
98         int ret = 0;
99         
100         yes = yes ? 1 : 0;
101         ret |= warm_change_cb_range(WCB_B_BIT, yes, gp2x_screens[0], 320*240*2);
102         ret |= warm_change_cb_range(WCB_B_BIT, yes, gp2x_screens[1], 320*240*2);
103         ret |= warm_change_cb_range(WCB_B_BIT, yes, gp2x_screens[2], 320*240*2);
104         ret |= warm_change_cb_range(WCB_B_BIT, yes, gp2x_screens[3], 320*240*2);
105
106         if (ret)
107                 fprintf(stderr, "could not make fb buferable.\n");
108         else
109                 printf("made fb buferable.\n");
110 }
111
112 /* common */
113 void plat_video_menu_enter(int is_rom_loaded)
114 {
115         if (gp2x_current_bpp != 16 || gp2x_dev_id == GP2X_DEV_WIZ) {
116                 /* try to switch nicely avoiding glitches */
117                 gp2x_video_wait_vsync();
118                 memset(gp2x_screens[0], 0, 320*240*2);
119                 memset(gp2x_screens[1], 0, 320*240*2);
120                 gp2x_video_flip2(); // might flip to fb2/3
121                 gp2x_video_flip2(); // ..so we do it again
122         }
123         else
124                 gp2x_video_flip2();
125
126         // switch to 16bpp
127         gp2x_video_changemode_ll(16);
128         gp2x_video_RGB_setscaling(0, 320, 240);
129 }
130
131 void plat_video_menu_begin(void)
132 {
133         g_menuscreen_ptr = g_screen_ptr;
134 }
135
136 void plat_video_menu_end(void)
137 {
138         gp2x_video_flip2();
139 }
140
141 void plat_early_init(void)
142 {
143         gp2x_soc_t soc;
144         FILE *f;
145
146         soc = soc_detect();
147         switch (soc)
148         {
149         case SOCID_MMSP2:
150                 default_cpu_clock = 200;
151                 gp2x_dev_id = GP2X_DEV_GP2X;
152                 break;
153         case SOCID_POLLUX:
154                 default_cpu_clock = 533;
155                 f = fopen("/dev/accel", "rb");
156                 if (f) {
157                         printf("detected Caanoo\n");
158                         gp2x_dev_id = GP2X_DEV_CAANOO;
159                         fclose(f);
160                 }
161                 else {
162                         printf("detected Wiz\n");
163                         gp2x_dev_id = GP2X_DEV_WIZ;
164                 }
165                 break;
166         default:
167                 printf("could not recognize SoC, running in dummy mode.\n");
168                 break;
169         }
170
171         // just use gettimeofday until plat_init()
172         gp2x_get_ticks_ms = plat_get_ticks_ms_good;
173         gp2x_get_ticks_us = plat_get_ticks_us_good;
174 }
175
176 void plat_init(void)
177 {
178         gp2x_soc_t soc;
179
180         soc = soc_detect();
181         switch (soc)
182         {
183         case SOCID_MMSP2:
184                 mmsp2_init();
185                 break;
186         case SOCID_POLLUX:
187                 pollux_init();
188                 break;
189         default:
190                 dummy_init();
191                 break;
192         }
193
194         warm_init();
195
196         gp2x_memset_all_buffers(0, 0, 320*240*2);
197
198         // use buffer2 for menubg to save mem (using only buffers 0, 1 in menu)
199         g_menubg_ptr = gp2x_screens[2];
200
201         // snd
202         sndout_oss_init();
203
204         if (gp2x_dev_id == GP2X_DEV_CAANOO)
205                 in_set_config(in_name_to_id("evdev:pollux-analog"), IN_CFG_KEY_NAMES,
206                                 caanoo_keys, sizeof(caanoo_keys));
207
208         gp2x_menu_init();
209 }
210
211 void plat_finish(void)
212 {
213         gp2x_soc_t soc;
214
215         warm_finish();
216
217         soc = soc_detect();
218         switch (soc)
219         {
220         case SOCID_MMSP2:
221                 mmsp2_finish();
222                 break;
223         case SOCID_POLLUX:
224                 pollux_finish();
225                 break;
226         default:
227                 dummy_finish();
228                 break;
229         }
230
231         sndout_oss_exit();
232 }
233