io.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*
  2. * PicoDrive
  3. * (C) notaz, 2007-2010
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "../libpicofe/menu.h"
  12. #include "../libpicofe/input.h"
  13. #include "../common/emu.h"
  14. #include "../common/input_pico.h"
  15. #include "../common/version.h"
  16. #include "log_io.h"
  17. int current_keys;
  18. #ifdef FBDEV
  19. #include "fbdev.h"
  20. #else
  21. #include <pthread.h>
  22. #include <semaphore.h>
  23. static int current_bpp = 16;
  24. static int current_pal[256];
  25. static const char *verstring = "PicoDrive " VERSION;
  26. static int scr_changed = 0, scr_w = 320, scr_h = 240;
  27. /* faking GP2X pad */
  28. enum { GP2X_UP=0x1, GP2X_LEFT=0x4, GP2X_DOWN=0x10, GP2X_RIGHT=0x40,
  29. GP2X_START=1<<8, GP2X_SELECT=1<<9, GP2X_L=1<<10, GP2X_R=1<<11,
  30. GP2X_A=1<<12, GP2X_B=1<<13, GP2X_X=1<<14, GP2X_Y=1<<15,
  31. GP2X_VOL_UP=1<<23, GP2X_VOL_DOWN=1<<22, GP2X_PUSH=1<<27 };
  32. static void key_press_event(int keycode)
  33. {
  34. switch (keycode)
  35. {
  36. case 111:
  37. case 0x62: current_keys |= GP2X_UP; break;
  38. case 116:
  39. case 0x68: current_keys |= GP2X_DOWN; break;
  40. case 113:
  41. case 0x64: current_keys |= GP2X_LEFT; break;
  42. case 114:
  43. case 0x66: current_keys |= GP2X_RIGHT; break;
  44. case 0x24: current_keys |= GP2X_START; break; // enter
  45. case 0x23: current_keys |= GP2X_SELECT;break; // ]
  46. case 0x34: current_keys |= GP2X_A; break; // z
  47. case 0x35: current_keys |= GP2X_X; break; // x
  48. case 0x36: current_keys |= GP2X_B; break; // c
  49. case 0x37: current_keys |= GP2X_Y; break; // v
  50. case 0x27: current_keys |= GP2X_L; break; // s
  51. case 0x28: current_keys |= GP2X_R; break; // d
  52. case 0x29: current_keys |= GP2X_PUSH; break; // f
  53. case 0x18: current_keys |= GP2X_VOL_DOWN;break; // q
  54. case 0x19: current_keys |= GP2X_VOL_UP;break; // w
  55. case 0x2d: log_io_clear(); break; // k
  56. case 0x2e: log_io_dump(); break; // l
  57. case 0x17: { // tab
  58. extern int PicoReset(void);
  59. PicoReset();
  60. break;
  61. }
  62. }
  63. }
  64. static void key_release_event(int keycode)
  65. {
  66. switch (keycode)
  67. {
  68. case 111:
  69. case 0x62: current_keys &= ~GP2X_UP; break;
  70. case 116:
  71. case 0x68: current_keys &= ~GP2X_DOWN; break;
  72. case 113:
  73. case 0x64: current_keys &= ~GP2X_LEFT; break;
  74. case 114:
  75. case 0x66: current_keys &= ~GP2X_RIGHT; break;
  76. case 0x24: current_keys &= ~GP2X_START; break; // enter
  77. case 0x23: current_keys &= ~GP2X_SELECT;break; // ]
  78. case 0x34: current_keys &= ~GP2X_A; break; // z
  79. case 0x35: current_keys &= ~GP2X_X; break; // x
  80. case 0x36: current_keys &= ~GP2X_B; break; // c
  81. case 0x37: current_keys &= ~GP2X_Y; break; // v
  82. case 0x27: current_keys &= ~GP2X_L; break; // s
  83. case 0x28: current_keys &= ~GP2X_R; break; // d
  84. case 0x29: current_keys &= ~GP2X_PUSH; break; // f
  85. case 0x18: current_keys &= ~GP2X_VOL_DOWN;break; // q
  86. case 0x19: current_keys &= ~GP2X_VOL_UP;break; // w
  87. }
  88. }
  89. /* --- */
  90. #include <X11/Xlib.h>
  91. #include <X11/Xutil.h>
  92. static Display *xlib_display;
  93. static Window xlib_window;
  94. static XImage *ximage;
  95. static void ximage_realloc(Display *display, Visual *visual)
  96. {
  97. void *xlib_screen;
  98. XLockDisplay(xlib_display);
  99. if (ximage != NULL)
  100. XDestroyImage(ximage);
  101. ximage = NULL;
  102. xlib_screen = calloc(scr_w * scr_h, 4);
  103. if (xlib_screen != NULL)
  104. ximage = XCreateImage(display, visual, 24, ZPixmap, 0,
  105. xlib_screen, scr_w, scr_h, 32, 0);
  106. if (ximage == NULL)
  107. fprintf(stderr, "failed to alloc ximage\n");
  108. XUnlockDisplay(xlib_display);
  109. }
  110. static void xlib_update(void)
  111. {
  112. Status xstatus;
  113. XLockDisplay(xlib_display);
  114. xstatus = XPutImage(xlib_display, xlib_window, DefaultGC(xlib_display, 0), ximage,
  115. 0, 0, 0, 0, g_screen_ppitch, g_screen_height);
  116. if (xstatus != 0)
  117. fprintf(stderr, "XPutImage %d\n", xstatus);
  118. XUnlockDisplay(xlib_display);
  119. }
  120. static void *xlib_threadf(void *targ)
  121. {
  122. unsigned int width, height, display_width, display_height;
  123. sem_t *sem = targ;
  124. XTextProperty windowName;
  125. Window win;
  126. XEvent report;
  127. Display *display;
  128. Visual *visual;
  129. int screen;
  130. XInitThreads();
  131. xlib_display = display = XOpenDisplay(NULL);
  132. if (display == NULL)
  133. {
  134. fprintf(stderr, "cannot connect to X server %s\n",
  135. XDisplayName(NULL));
  136. sem_post(sem);
  137. return NULL;
  138. }
  139. visual = DefaultVisual(display, 0);
  140. if (visual->class != TrueColor)
  141. {
  142. fprintf(stderr, "cannot handle non true color visual\n");
  143. XCloseDisplay(display);
  144. sem_post(sem);
  145. return NULL;
  146. }
  147. printf("X vendor: %s, rel: %d, display: %s, protocol ver: %d.%d\n", ServerVendor(display),
  148. VendorRelease(display), DisplayString(display), ProtocolVersion(display),
  149. ProtocolRevision(display));
  150. screen = DefaultScreen(display);
  151. ximage_realloc(display, visual);
  152. sem_post(sem);
  153. display_width = DisplayWidth(display, screen);
  154. display_height = DisplayHeight(display, screen);
  155. xlib_window = win = XCreateSimpleWindow(display,
  156. RootWindow(display, screen),
  157. display_width / 2 - scr_w / 2,
  158. display_height / 2 - scr_h / 2,
  159. scr_w + 2, scr_h + 2, 1,
  160. BlackPixel(display, screen),
  161. BlackPixel(display, screen));
  162. XStringListToTextProperty((char **)&verstring, 1, &windowName);
  163. XSetWMName(display, win, &windowName);
  164. XSelectInput(display, win, ExposureMask |
  165. KeyPressMask | KeyReleaseMask |
  166. StructureNotifyMask);
  167. XMapWindow(display, win);
  168. while (1)
  169. {
  170. XNextEvent(display, &report);
  171. switch (report.type)
  172. {
  173. case Expose:
  174. while (XCheckTypedEvent(display, Expose, &report))
  175. ;
  176. xlib_update();
  177. break;
  178. case ConfigureNotify:
  179. width = report.xconfigure.width;
  180. height = report.xconfigure.height;
  181. if (scr_w != width - 2 || scr_h != height - 2) {
  182. scr_w = width - 2;
  183. scr_h = height - 2;
  184. scr_changed = 1;
  185. }
  186. break;
  187. case ButtonPress:
  188. break;
  189. case KeyPress:
  190. key_press_event(report.xkey.keycode);
  191. break;
  192. case KeyRelease:
  193. key_release_event(report.xkey.keycode);
  194. break;
  195. default:
  196. break;
  197. }
  198. }
  199. }
  200. static void xlib_init(void)
  201. {
  202. pthread_t x_thread;
  203. sem_t xlib_sem;
  204. sem_init(&xlib_sem, 0, 0);
  205. pthread_create(&x_thread, NULL, xlib_threadf, &xlib_sem);
  206. pthread_detach(x_thread);
  207. sem_wait(&xlib_sem);
  208. sem_destroy(&xlib_sem);
  209. }
  210. /* --- */
  211. static void realloc_screen(void)
  212. {
  213. int size = scr_w * scr_h * 2;
  214. g_screen_width = g_menuscreen_w = scr_w;
  215. g_screen_height = g_menuscreen_h = scr_h;
  216. g_screen_ppitch = g_menuscreen_pp = scr_w;
  217. g_screen_ptr = realloc(g_screen_ptr, size);
  218. g_menubg_ptr = realloc(g_menubg_ptr, size);
  219. memset(g_screen_ptr, 0, size);
  220. memset(g_menubg_ptr, 0, size);
  221. scr_changed = 0;
  222. }
  223. void plat_video_flip(void)
  224. {
  225. unsigned int *image;
  226. int pixel_count, i;
  227. if (ximage == NULL)
  228. return;
  229. pixel_count = g_screen_ppitch * g_screen_height;
  230. image = (void *)ximage->data;
  231. if (current_bpp == 8)
  232. {
  233. unsigned char *pixels = g_screen_ptr;
  234. int pix;
  235. for (i = 0; i < pixel_count; i++)
  236. {
  237. pix = current_pal[pixels[i]];
  238. image[i] = pix;
  239. }
  240. }
  241. else
  242. {
  243. unsigned short *pixels = g_screen_ptr;
  244. for (i = 0; i < pixel_count; i++)
  245. {
  246. /* in: rrrr rggg gggb bbbb */
  247. /* out: rrrr r000 gggg gg00 bbbb b000 */
  248. image[i] = (pixels[i] << 8) & 0xf80000;
  249. image[i] |= (pixels[i] << 5) & 0x00fc00;
  250. image[i] |= (pixels[i] << 3) & 0x0000f8;
  251. }
  252. }
  253. xlib_update();
  254. if (scr_changed) {
  255. realloc_screen();
  256. ximage_realloc(xlib_display, DefaultVisual(xlib_display, 0));
  257. // propagate new ponters to renderers
  258. plat_video_set_buffer(g_screen_ptr);
  259. }
  260. }
  261. void plat_video_wait_vsync(void)
  262. {
  263. }
  264. #endif // !FBDEV
  265. void plat_early_init(void)
  266. {
  267. }
  268. void plat_init(void)
  269. {
  270. #ifdef FBDEV
  271. int ret, w, h;
  272. ret = vout_fbdev_init(&w, &h);
  273. if (ret != 0)
  274. exit(1);
  275. g_screen_width = g_menuscreen_w = w;
  276. g_screen_height = g_menuscreen_h = h;
  277. g_screen_ppitch = g_menuscreen_pp = w;
  278. g_menubg_ptr = realloc(g_menubg_ptr, w * g_screen_height * 2);
  279. #else
  280. realloc_screen();
  281. memset(g_screen_ptr, 0, g_screen_width * g_screen_height * 2);
  282. xlib_init();
  283. #endif
  284. }
  285. void plat_finish(void)
  286. {
  287. #ifdef FBDEV
  288. vout_fbdev_finish();
  289. #else
  290. free(g_screen_ptr);
  291. #endif
  292. }
  293. /* misc */
  294. int mp3_get_bitrate(void *f, int size)
  295. {
  296. return 128;
  297. }
  298. void mp3_start_play(void *f, int pos)
  299. {
  300. }
  301. void mp3_update(int *buffer, int length, int stereo)
  302. {
  303. }
  304. #include <linux/input.h>
  305. struct in_default_bind in_evdev_defbinds[] =
  306. {
  307. /* MXYZ SACB RLDU */
  308. { KEY_UP, IN_BINDTYPE_PLAYER12, 0 },
  309. { KEY_DOWN, IN_BINDTYPE_PLAYER12, 1 },
  310. { KEY_LEFT, IN_BINDTYPE_PLAYER12, 2 },
  311. { KEY_RIGHT, IN_BINDTYPE_PLAYER12, 3 },
  312. { KEY_S, IN_BINDTYPE_PLAYER12, 4 }, /* B */
  313. { KEY_D, IN_BINDTYPE_PLAYER12, 5 }, /* C */
  314. { KEY_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */
  315. { KEY_ENTER, IN_BINDTYPE_PLAYER12, 7 },
  316. { KEY_BACKSLASH, IN_BINDTYPE_EMU, PEVB_MENU },
  317. { 0, 0, 0 }
  318. };