cc68a136 |
1 | /* faking/emulating gp2x.c by using gtk */ |
2 | #include <stdio.h> |
3 | #include <stdlib.h> |
4 | #include <string.h> |
5 | #include <pthread.h> |
69996cb7 |
6 | #include <semaphore.h> |
cc68a136 |
7 | #include <gtk/gtk.h> |
8 | |
9 | #include <unistd.h> |
10 | #include <sys/types.h> |
11 | #include <sys/stat.h> |
cc68a136 |
12 | #include <fcntl.h> |
13 | #include <errno.h> |
14 | |
15 | #include "../gp2x/emu.h" |
16 | #include "../gp2x/gp2x.h" |
cc68a136 |
17 | #include "../gp2x/version.h" |
e5ab6faf |
18 | #include "sndout_oss.h" |
19 | #include "usbjoy.h" |
cc68a136 |
20 | |
4f65685b |
21 | #include "log_io.h" |
22 | |
cc68a136 |
23 | void *gp2x_screen; |
24 | static int current_bpp = 8; |
25 | static int current_pal[256]; |
26 | static unsigned long current_keys = 0; |
cc68a136 |
27 | static const char *verstring = "PicoDrive " VERSION; |
28 | |
29 | // dummies |
30 | char *ext_menu = 0, *ext_state = 0; |
f53f286a |
31 | int mix_32_to_16l_level; |
cc68a136 |
32 | |
33 | /* gtk */ |
34 | struct gtk_global_struct |
35 | { |
36 | GtkWidget *window; |
37 | GtkWidget *pixmap1; |
38 | } gtk_items; |
39 | |
40 | |
41 | static gboolean delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) |
42 | { |
43 | return FALSE; |
44 | } |
45 | |
46 | static void destroy (GtkWidget *widget, gpointer data) |
47 | { |
48 | gtk_main_quit (); |
49 | } |
50 | |
51 | static gint key_press_event (GtkWidget *widget, GdkEventKey *event) |
52 | { |
53 | switch (event->hardware_keycode) |
54 | { |
55 | case 0x62: current_keys |= GP2X_UP; break; |
56 | case 0x68: current_keys |= GP2X_DOWN; break; |
57 | case 0x64: current_keys |= GP2X_LEFT; break; |
58 | case 0x66: current_keys |= GP2X_RIGHT; break; |
59 | case 0x24: current_keys |= GP2X_START; break; // enter |
60 | case 0x23: current_keys |= GP2X_SELECT;break; // ] |
61 | case 0x34: current_keys |= GP2X_A; break; // z |
62 | case 0x35: current_keys |= GP2X_X; break; // x |
63 | case 0x36: current_keys |= GP2X_B; break; // c |
64 | case 0x37: current_keys |= GP2X_Y; break; // v |
65 | case 0x27: current_keys |= GP2X_L; break; // s |
66 | case 0x28: current_keys |= GP2X_R; break; // d |
67 | case 0x29: current_keys |= GP2X_PUSH; break; // f |
68 | case 0x18: current_keys |= GP2X_VOL_DOWN;break; // q |
69 | case 0x19: current_keys |= GP2X_VOL_UP;break; // w |
4f65685b |
70 | case 0x2d: log_io_clear(); break; // k |
71 | case 0x2e: log_io_dump(); break; // l |
1e6b5e39 |
72 | case 0x17: { // tab |
73 | extern int PicoReset(void); |
74 | PicoReset(); |
75 | break; |
76 | } |
cc68a136 |
77 | } |
78 | |
79 | return 0; |
80 | } |
81 | |
82 | static gint key_release_event (GtkWidget *widget, GdkEventKey *event) |
83 | { |
84 | switch (event->hardware_keycode) |
85 | { |
86 | case 0x62: current_keys &= ~GP2X_UP; break; |
87 | case 0x68: current_keys &= ~GP2X_DOWN; break; |
88 | case 0x64: current_keys &= ~GP2X_LEFT; break; |
89 | case 0x66: current_keys &= ~GP2X_RIGHT; break; |
90 | case 0x24: current_keys &= ~GP2X_START; break; // enter |
91 | case 0x23: current_keys &= ~GP2X_SELECT;break; // ] |
92 | case 0x34: current_keys &= ~GP2X_A; break; // z |
93 | case 0x35: current_keys &= ~GP2X_X; break; // x |
94 | case 0x36: current_keys &= ~GP2X_B; break; // c |
95 | case 0x37: current_keys &= ~GP2X_Y; break; // v |
96 | case 0x27: current_keys &= ~GP2X_L; break; // s |
97 | case 0x28: current_keys &= ~GP2X_R; break; // d |
98 | case 0x29: current_keys &= ~GP2X_PUSH; break; // f |
99 | case 0x18: current_keys &= ~GP2X_VOL_DOWN;break; // q |
100 | case 0x19: current_keys &= ~GP2X_VOL_UP;break; // w |
101 | } |
102 | |
103 | return 0; |
104 | } |
105 | |
69996cb7 |
106 | static void *gtk_threadf(void *targ) |
cc68a136 |
107 | { |
108 | int argc = 0; |
109 | char *argv[] = { "" }; |
110 | GtkWidget *box; |
69996cb7 |
111 | sem_t *sem = targ; |
cc68a136 |
112 | |
113 | g_thread_init (NULL); |
114 | gdk_threads_init (); |
115 | gdk_set_locale (); |
116 | gtk_init (&argc, (char ***) &argv); |
117 | |
118 | /* create new window */ |
119 | gtk_items.window = gtk_window_new (GTK_WINDOW_TOPLEVEL); |
120 | g_signal_connect (G_OBJECT (gtk_items.window), "delete_event", |
121 | G_CALLBACK (delete_event), NULL); |
122 | |
123 | g_signal_connect (G_OBJECT (gtk_items.window), "destroy", |
124 | G_CALLBACK (destroy), NULL); |
125 | |
126 | g_signal_connect (G_OBJECT (gtk_items.window), "key_press_event", |
127 | G_CALLBACK (key_press_event), NULL); |
128 | |
129 | g_signal_connect (G_OBJECT (gtk_items.window), "key_release_event", |
130 | G_CALLBACK (key_release_event), NULL); |
131 | |
132 | gtk_container_set_border_width (GTK_CONTAINER (gtk_items.window), 2); |
133 | gtk_window_set_title ((GtkWindow *) gtk_items.window, verstring); |
134 | |
135 | box = gtk_hbox_new(FALSE, 0); |
136 | gtk_widget_show(box); |
137 | gtk_container_add (GTK_CONTAINER (gtk_items.window), box); |
138 | |
139 | /* live pixmap */ |
140 | gtk_items.pixmap1 = gtk_image_new (); |
141 | gtk_container_add (GTK_CONTAINER (box), gtk_items.pixmap1); |
142 | gtk_widget_show (gtk_items.pixmap1); |
143 | gtk_widget_set_size_request (gtk_items.pixmap1, 320, 240); |
144 | |
145 | gtk_widget_show (gtk_items.window); |
146 | |
69996cb7 |
147 | sem_post(sem); |
148 | |
149 | gtk_main(); |
150 | |
151 | printf("linux: gtk thread finishing\n"); |
152 | exit(1); |
153 | |
154 | return NULL; |
155 | } |
156 | |
157 | static void gtk_initf(void) |
158 | { |
159 | pthread_t gtk_thread; |
160 | sem_t sem; |
161 | sem_init(&sem, 0, 0); |
162 | |
163 | pthread_create(>k_thread, NULL, gtk_threadf, &sem); |
164 | pthread_detach(gtk_thread); |
cc68a136 |
165 | |
69996cb7 |
166 | sem_wait(&sem); |
167 | sem_close(&sem); |
cc68a136 |
168 | } |
169 | |
170 | void finalize_image(guchar *pixels, gpointer data) |
171 | { |
172 | free(pixels); |
173 | } |
174 | |
175 | /* --- */ |
176 | |
177 | void gp2x_init(void) |
178 | { |
179 | printf("entering init()\n"); fflush(stdout); |
180 | |
181 | gp2x_screen = malloc(320*240*2 + 320*2); |
83bd0b76 |
182 | memset(gp2x_screen, 0, 320*240*2 + 320*2); |
cc68a136 |
183 | |
184 | // snd |
e5ab6faf |
185 | sndout_oss_init(); |
cc68a136 |
186 | |
187 | gtk_initf(); |
188 | |
e5ab6faf |
189 | usbjoy_init(); |
cc68a136 |
190 | |
191 | printf("exitting init()\n"); fflush(stdout); |
192 | } |
193 | |
194 | void gp2x_deinit(void) |
195 | { |
196 | free(gp2x_screen); |
e5ab6faf |
197 | sndout_oss_exit(); |
198 | usbjoy_deinit(); |
cc68a136 |
199 | } |
200 | |
201 | /* video */ |
202 | void gp2x_video_flip(void) |
203 | { |
204 | GdkPixbuf *pixbuf; |
205 | unsigned char *image; |
206 | int i; |
207 | |
208 | gdk_threads_enter(); |
209 | |
210 | image = malloc (320*240*3); |
211 | if (image == NULL) |
212 | { |
213 | gdk_threads_leave(); |
214 | return; |
215 | } |
216 | |
217 | if (current_bpp == 8) |
218 | { |
219 | unsigned char *pixels = gp2x_screen; |
220 | int pix; |
221 | |
222 | for (i = 0; i < 320*240; i++) |
223 | { |
224 | pix = current_pal[pixels[i]]; |
225 | image[3 * i + 0] = pix >> 16; |
226 | image[3 * i + 1] = pix >> 8; |
227 | image[3 * i + 2] = pix; |
228 | } |
229 | } |
230 | else |
231 | { |
232 | unsigned short *pixels = gp2x_screen; |
233 | |
234 | for (i = 0; i < 320*240; i++) |
235 | { |
236 | /* in: rrrr rggg gggb bbbb */ |
237 | /* out: rrrr r000 gggg gg00 bbbb b000 */ |
238 | image[3 * i + 0] = (pixels[i] >> 8) & 0xf8; |
239 | image[3 * i + 1] = (pixels[i] >> 3) & 0xfc; |
240 | image[3 * i + 2] = (pixels[i] << 3); |
241 | } |
242 | } |
243 | |
244 | pixbuf = gdk_pixbuf_new_from_data (image, GDK_COLORSPACE_RGB, |
245 | FALSE, 8, 320, 240, 320*3, finalize_image, NULL); |
246 | gtk_image_set_from_pixbuf (GTK_IMAGE (gtk_items.pixmap1), pixbuf); |
247 | g_object_unref (pixbuf); |
248 | |
249 | gdk_threads_leave(); |
250 | } |
251 | |
e11c5548 |
252 | void gp2x_video_flip2(void) |
253 | { |
254 | gp2x_video_flip(); |
255 | } |
256 | |
cc68a136 |
257 | void gp2x_video_changemode(int bpp) |
258 | { |
259 | current_bpp = bpp; |
260 | } |
261 | |
e11c5548 |
262 | void gp2x_video_changemode2(int bpp) |
263 | { |
264 | current_bpp = bpp; |
265 | } |
266 | |
cc68a136 |
267 | void gp2x_video_setpalette(int *pal, int len) |
268 | { |
269 | memcpy(current_pal, pal, len*4); |
270 | } |
271 | |
a12e0116 |
272 | void gp2x_video_flush_cache(void) |
273 | { |
274 | } |
275 | |
2433f409 |
276 | void gp2x_video_RGB_setscaling(int v_offs, int W, int H) |
cc68a136 |
277 | { |
278 | } |
279 | |
68cba51e |
280 | void gp2x_memcpy_buffers(int buffers, void *data, int offset, int len) |
281 | { |
a12e0116 |
282 | if ((char *)gp2x_screen + offset != data) |
283 | memcpy((char *)gp2x_screen + offset, data, len); |
68cba51e |
284 | } |
285 | |
cc68a136 |
286 | void gp2x_memcpy_all_buffers(void *data, int offset, int len) |
287 | { |
288 | memcpy((char *)gp2x_screen + offset, data, len); |
289 | } |
290 | |
291 | |
292 | void gp2x_memset_all_buffers(int offset, int byte, int len) |
293 | { |
294 | memset((char *)gp2x_screen + offset, byte, len); |
295 | } |
296 | |
e11c5548 |
297 | void gp2x_pd_clone_buffer2(void) |
298 | { |
a12e0116 |
299 | memset(gp2x_screen, 0, 320*240*2); |
e11c5548 |
300 | } |
cc68a136 |
301 | |
cc68a136 |
302 | /* joy */ |
303 | unsigned long gp2x_joystick_read(int allow_usb_joy) |
304 | { |
305 | unsigned long value = current_keys; |
306 | int i; |
307 | |
308 | if (allow_usb_joy && num_of_joys > 0) { |
309 | // check the usb joy as well.. |
e5ab6faf |
310 | usbjoy_update(); |
cc68a136 |
311 | for (i = 0; i < num_of_joys; i++) |
e5ab6faf |
312 | value |= usbjoy_check(i); |
cc68a136 |
313 | } |
314 | |
315 | return value; |
316 | } |
317 | |
85a4b5a4 |
318 | int gp2x_touchpad_read(int *x, int *y) |
319 | { |
320 | return -1; |
321 | } |
322 | |
cc68a136 |
323 | /* 940 */ |
324 | int crashed_940 = 0; |
325 | void Pause940(int yes) |
326 | { |
327 | } |
328 | |
b837b69b |
329 | void Reset940(int yes, int bank) |
cc68a136 |
330 | { |
331 | } |
332 | |
333 | /* faking gp2x cpuctrl.c */ |
334 | void cpuctrl_init(void) |
335 | { |
336 | } |
337 | |
338 | void cpuctrl_deinit(void) |
339 | { |
340 | } |
341 | |
342 | void set_FCLK(unsigned MHZ) |
343 | { |
344 | } |
345 | |
346 | void Disable_940(void) |
347 | { |
348 | } |
349 | |
350 | void gp2x_video_wait_vsync(void) |
351 | { |
352 | } |
353 | |
354 | void set_RAM_Timings(int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD) |
355 | { |
356 | } |
357 | |
82bc9cdd |
358 | void set_gamma(int g100, int A_SNs_curve) |
cc68a136 |
359 | { |
360 | } |
361 | |
4e8a534c |
362 | void set_LCD_custom_rate(int rate) |
363 | { |
364 | } |
365 | |
366 | void unset_LCD_custom_rate(void) |
367 | { |
368 | } |
cc68a136 |
369 | |
370 | /* squidgehack.c */ |
371 | int mmuhack(void) |
372 | { |
373 | return 0; |
374 | } |
375 | |
376 | |
377 | int mmuunhack(void) |
378 | { |
379 | return 0; |
380 | } |
381 | |
382 | |
383 | /* misc */ |
384 | void spend_cycles(int c) |
385 | { |
46969540 |
386 | usleep(c/200); |
cc68a136 |
387 | } |
388 | |
ca61ee42 |
389 | /* lprintf */ |
390 | void lprintf(const char *fmt, ...) |
391 | { |
392 | va_list vl; |
cc68a136 |
393 | |
ca61ee42 |
394 | va_start(vl, fmt); |
395 | vprintf(fmt, vl); |
396 | va_end(vl); |
397 | } |
cc68a136 |
398 | |