frontend: key config: save it and make more intuitive
[pcsx_rearmed.git] / maemo / hildon.c
1 #include <gtk/gtk.h>
2 #include <glib.h>
3 #include <stdlib.h>
4 #include <stdint.h>
5 #include <unistd.h>
6 #include <hildon/hildon.h>
7 #include "plugin_lib.h"
8 #include "../libpcsxcore/psemu_plugin_defs.h"
9
10 #define X_RES           800
11 #define Y_RES           480
12 #define D_WIDTH                 640
13 #define D_HEIGHT                480
14
15 static GdkImage *image;
16 static HildonAnimationActor *actor;
17 static GtkWidget *window, *drawing;
18
19 void *pl_fbdev_buf;
20 int in_type = PSE_PAD_TYPE_STANDARD;
21 int in_keystate, in_a1[2], in_a2[2];
22
23 static int keymap[65536];
24
25 // map psx4m compatible keymap to PSX keys
26 static const unsigned char keymap2[14] = {
27         DKEY_LEFT,   // 0
28         DKEY_RIGHT,
29         DKEY_UP,
30         DKEY_DOWN,
31         DKEY_CIRCLE,
32         DKEY_CROSS,  // 5
33         DKEY_TRIANGLE,
34         DKEY_SQUARE,
35         DKEY_SELECT,
36         DKEY_START,
37         DKEY_L2,     // 10
38         DKEY_R2,
39         DKEY_L1,
40         DKEY_R1,
41 };
42
43 void hildon_quit()
44 {
45         gtk_main_quit();
46         exit(0);
47 }
48
49 static void
50 window_key_proxy(GtkWidget *widget,
51                      GdkEventKey *event,
52                      gpointer user_data)
53 {
54         int key, psxkey1 = -1, psxkey2 = -1;
55
56         key = keymap[event->hardware_keycode];
57         if (key < 0)
58                 return;
59
60         if (key < ARRAY_SIZE(keymap2))
61                 psxkey1 = keymap2[key];
62         else switch (key) {
63                 case 14:
64                         hildon_quit();
65                         break;
66                 case 15:
67                         psxkey1 = DKEY_UP;
68                         psxkey2 = DKEY_LEFT;
69                         break;
70                 case 16:
71                         psxkey1 = DKEY_UP;
72                         psxkey2 = DKEY_RIGHT;
73                         break;
74                 case 17:
75                         psxkey1 = DKEY_DOWN;
76                         psxkey2 = DKEY_LEFT;
77                         break;
78                 case 18:
79                         psxkey1 = DKEY_DOWN;
80                         psxkey2 = DKEY_RIGHT;
81                         break;
82                 case 19:
83                         //SaveState(cfile);
84                         return;
85                 case 20:
86                         //LoadState(cfile);
87                         return;
88         }
89
90         if (event->type == GDK_KEY_PRESS) {
91                 if (psxkey1 >= 0)
92                         in_keystate |= 1 << psxkey1;
93                 if (psxkey2 >= 0)
94                         in_keystate |= 1 << psxkey2;
95         }
96         else if (event->type == GDK_KEY_RELEASE) {
97                 if (psxkey1 >= 0)
98                         in_keystate &= ~(1 << psxkey1);
99                 if (psxkey2 >= 0)
100                         in_keystate &= ~(1 << psxkey2);
101         }
102 }
103
104 void plat_finish()
105 {
106         hildon_quit();
107 }
108
109 void maemo_init(int *argc, char ***argv)
110 {
111         FILE* pFile;
112         pFile = fopen("/opt/psx4m/keys", "r"); // assume the file exists and has data
113         int ch;
114         int i=0;
115         for (i=0;i<65536;i++)
116                 keymap[i]=164;
117         if (NULL != pFile) {
118                 for(i=0;i<21;i++){
119                         fscanf(pFile, "%i",&ch);
120                         keymap[ch]=i;
121                 }
122                 fclose(pFile);
123         }
124         
125         gtk_init (argc, argv);
126
127         window = hildon_stackable_window_new ();
128         gtk_widget_realize (window);
129         gtk_window_fullscreen (GTK_WINDOW(window));
130         g_signal_connect (G_OBJECT (window), "key-press-event",
131                                 G_CALLBACK (window_key_proxy), NULL);
132         g_signal_connect (G_OBJECT (window), "key-release-event",
133                                 G_CALLBACK (window_key_proxy), NULL);
134         g_signal_connect (G_OBJECT (window), "delete_event",
135                                 G_CALLBACK (hildon_quit), NULL);
136         gtk_widget_add_events (window,
137                                 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
138
139         actor = HILDON_ANIMATION_ACTOR (hildon_animation_actor_new());
140         hildon_animation_actor_set_position (actor, (X_RES - D_WIDTH)/2, (Y_RES - D_HEIGHT)/2 );
141         hildon_animation_actor_set_parent (actor, GTK_WINDOW (window));
142
143         drawing = gtk_image_new ();
144
145         gtk_container_add (GTK_CONTAINER (actor), drawing);
146
147         gtk_widget_show_all (GTK_WIDGET (actor));
148         gtk_widget_show_all (GTK_WIDGET (window));
149 }
150
151 void *pl_fbdev_set_mode(int w, int h, int bpp)
152 {
153         if (w <= 0 || h <= 0)
154                 return pl_fbdev_buf;
155
156         if (image) gdk_image_destroy(image);
157         image = gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), w, h );
158
159         pl_fbdev_buf = (void *) image->mem;
160
161         gtk_image_set_from_image (GTK_IMAGE(drawing), image, NULL);
162
163         gtk_window_resize (GTK_WINDOW (actor), w, h);
164         hildon_animation_actor_set_scale (actor,
165                                 (gdouble)D_WIDTH / (gdouble)w,
166                                 (gdouble)D_HEIGHT / (gdouble)h
167         );
168
169         return pl_fbdev_buf;
170 }
171
172 void *pl_fbdev_flip(void)
173 {
174         gtk_widget_queue_draw (drawing);
175         return pl_fbdev_buf;
176 }
177
178 void pl_frame_limit(void)
179 {
180         extern void CheckFrameRate(void);
181         //CheckFrameRate();
182
183         /* process GTK+ events */
184         while (gtk_events_pending())
185                 gtk_main_iteration();
186 }
187
188 void pl_fbdev_close(void)
189 {
190 }
191
192 int pl_fbdev_open(void)
193 {
194         return 0;
195 }
196
197 static void pl_get_layer_pos(int *x, int *y, int *w, int *h)
198 {
199         *x = 0;
200         *y = 0;
201         *w = 800;
202         *h = 640;
203 }
204
205 extern int UseFrameSkip; // hmh
206
207 const struct rearmed_cbs pl_rearmed_cbs = {
208         pl_get_layer_pos,
209         pl_fbdev_open,
210         pl_fbdev_set_mode,
211         pl_fbdev_flip,
212         pl_fbdev_close,
213         &UseFrameSkip,
214 };
215