1 #ifdef WANT_LIBCO
2 #include <libco.h>
3 #else
4 #include <rthreads/rthreads.h>
5 #endif
6
7 #if (HAS_DRZ80 || HAS_CYCLONE)
8 #include "frontend_list.h"
9 #endif
10
11 #include <stdarg.h>
12 #include <sys/time.h>
13 #include <libretro.h>
14 #include "mame.h"
15 #include "cpuintrf.h"
16 #include "osdepend.h"
17 #include "driver.h"
18 #include "allegro.h"
19 #include <file/file_path.h>
20
21 #ifndef RETROK_TILDE
22 #define RETROK_TILDE 178
23 #endif
24
25 #ifdef _WIN32
26 char slash = '\\';
27 #else
28 char slash = '/';
29 #endif
30
31 char *IMAMEBASEPATH = NULL;
32 char *IMAMESAMPLEPATH = NULL;
33
34 const char *retro_save_directory;
35 const char *retro_system_directory;
36 const char *retro_content_directory;
37 char core_save_directory[1024];
38 char core_sys_directory[1024];
39
40 unsigned retro_hook_quit;
41 volatile static unsigned audio_done;
42 volatile static unsigned video_done;
43 volatile static unsigned mame_sleep;
44 #ifdef WANT_LIBCO
45 int libco_quit=0;
46 static cothread_t core_thread;
47 static cothread_t main_thread;
48 #else
49 static sthread_t *run_thread = NULL;
50 static scond_t *libretro_cond = NULL;
51 static slock_t *libretro_mutex = NULL;
52 #endif
53
54 int game_index = -1;
55 unsigned short *gp2x_screen15;
56 int thread_done = 0;
57 extern int gfx_xoffset;
58 extern int gfx_yoffset;
59 extern int gfx_width;
60 extern int gfx_height;
61 extern int usestereo;
62 extern int samples_per_frame;
63 extern short *samples_buffer;
64 extern short *conversion_buffer;
65 extern int joy_pressed[40];
66 extern int key[KEY_MAX];
67
68 extern char *nvdir, *hidir, *cfgdir, *inpdir, *stadir, *memcarddir;
69 extern char *artworkdir, *screenshotdir, *alternate_name;
70 extern char *cheatdir;
71
72 void decompose_rom_sample_path(char *rompath, char *samplepath);
73 void init_joy_list(void);
74
75 extern UINT32 create_path_recursive(char *path);
76
77 #if defined(_3DS)
78 void* linearMemAlign(size_t size, size_t alignment);
79 void linearFree(void* mem);
80 #endif
81
logerror(const char * text,...)82 void CLIB_DECL logerror(const char *text,...)
83 {
84 #ifdef DISABLE_ERROR_LOGGING
85 va_list arg;
86 va_start(arg,text);
87 vprintf(text,arg);
88 va_end(arg);
89 #endif
90 }
91
92 int global_showinfo = 1;
93 int emulated_width;
94 int emulated_height;
95 int safe_render_path = 1;
96 unsigned short gp2x_palette[512];
97 int gp2x_pal_50hz=0;
98 int global_fps = 1;
99 int rotate_controls = 0;
100 int num_of_joys = 2;
101 int soundcard;
102 int attenuation = 0;
103
gp2x_printf(char * fmt,...)104 void gp2x_printf(char* fmt, ...)
105 {
106 va_list marker;
107
108 va_start(marker, fmt);
109 vprintf(fmt, marker);
110 va_end(marker);
111 }
112
gp2x_set_video_mode(int bpp,int width,int height)113 void gp2x_set_video_mode(int bpp,int width,int height)
114 {
115 (void)bpp;
116 (void)width;
117 (void)height;
118 }
119
gp2x_video_setpalette(void)120 void gp2x_video_setpalette(void)
121 {
122 }
123
gp2x_joystick_read(int n)124 unsigned long gp2x_joystick_read(int n)
125 {
126 (void)n;
127 }
128
osd_init(void)129 int osd_init(void)
130 {
131 return 0;
132 }
133
osd_exit(void)134 void osd_exit(void)
135 {
136 }
137
screen_reinit(void)138 int screen_reinit(void)
139 {
140 return 1;
141 }
142
143 static retro_video_refresh_t video_cb;
144 static retro_audio_sample_t audio_cb;
145 static retro_audio_sample_batch_t audio_batch_cb;
146 static retro_environment_t environ_cb;
147 static retro_input_poll_t input_poll_cb;
148 static retro_input_state_t input_state_cb;
149
150 static bool libretro_supports_bitmasks = false;
151
152 unsigned skip_disclaimer = 0;
153
update_variables(void)154 static void update_variables(void)
155 {
156 struct retro_variable var;
157
158 var.value = NULL;
159 var.key = "mame2000-skip_disclaimer";
160
161 if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
162 {
163 if(strcmp(var.value, "enabled") == 0)
164 skip_disclaimer = 1;
165 else
166 skip_disclaimer = 0;
167 }
168 else
169 skip_disclaimer = 0;
170
171 var.value = NULL;
172 var.key = "mame2000-show_gameinfo";
173
174 if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
175 {
176 if(strcmp(var.value, "enabled") == 0)
177 global_showinfo = 1;
178 else
179 global_showinfo = 0;
180 }
181 else
182 global_showinfo = 0;
183 }
184
retro_set_environment(retro_environment_t cb)185 void retro_set_environment(retro_environment_t cb)
186 {
187 static const struct retro_variable vars[] = {
188 { "mame2000-skip_disclaimer", "Skip Disclaimer; enabled|disabled" },
189 { "mame2000-show_gameinfo", "Show Game Information; disabled|enabled" },
190 { NULL, NULL },
191 };
192 environ_cb = cb;
193
194 cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
195 }
196
retro_set_audio_sample(retro_audio_sample_t cb)197 void retro_set_audio_sample(retro_audio_sample_t cb)
198 {
199 audio_cb = cb;
200 }
201
retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)202 void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
203 {
204 audio_batch_cb = cb;
205 }
206
retro_set_input_poll(retro_input_poll_t cb)207 void retro_set_input_poll(retro_input_poll_t cb)
208 {
209 input_poll_cb = cb;
210 }
211
retro_set_input_state(retro_input_state_t cb)212 void retro_set_input_state(retro_input_state_t cb)
213 {
214 input_state_cb = cb;
215 }
216
retro_set_video_refresh(retro_video_refresh_t cb)217 void retro_set_video_refresh(retro_video_refresh_t cb)
218 {
219 video_cb = cb;
220 }
221
retro_reset(void)222 void retro_reset(void)
223 {
224 machine_reset();
225 }
226
update_input(void)227 static void update_input(void)
228 {
229 #define RK(port,key) input_state_cb(port, RETRO_DEVICE_KEYBOARD, 0,RETROK_##key)
230 #define JS(port, button) joypad_bits & (1 << RETRO_DEVICE_ID_JOYPAD_##button)
231 int i, j, c = 0;
232 input_poll_cb();
233
234 key[KEY_TAB] = 0;
235 for (i = 0; i < 4; i++)
236 {
237 key[KEY_1 + i] = 0;
238 key[KEY_5 + i] = 0;
239 }
240
241 for (i = 0; i < 4; i++)
242 {
243 int16_t joypad_bits;
244
245 if (libretro_supports_bitmasks)
246 joypad_bits = input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
247 else
248 {
249 joypad_bits = 0;
250 for (j = 0; j < (RETRO_DEVICE_ID_JOYPAD_R3+1); j++)
251 joypad_bits |= input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, j) ? (1 << j) : 0;
252 }
253
254 key[KEY_1 + i] |= JS(i, START);
255 key[KEY_5 + i] |= JS(i, SELECT);
256 joy_pressed[c++] = JS(i, LEFT);
257 joy_pressed[c++] = JS(i, RIGHT);
258 joy_pressed[c++] = JS(i, UP);
259 joy_pressed[c++] = JS(i, DOWN);
260 joy_pressed[c++] = JS(i, B);
261 joy_pressed[c++] = JS(i, A);
262 joy_pressed[c++] = JS(i, Y);
263 joy_pressed[c++] = JS(i, X);
264 joy_pressed[c++] = JS(i, L);
265 joy_pressed[c++] = JS(i, R);
266
267 key[KEY_TAB] |= JS(i, R2);
268 }
269
270 key[KEY_A] =RK(0, a);
271 key[KEY_B] =RK(0, b);
272 key[KEY_C] =RK(0, c);
273 key[KEY_D] =RK(0, d);
274 key[KEY_E] =RK(0, e);
275 key[KEY_F] =RK(0, f);
276 key[KEY_G] =RK(0, g);
277 key[KEY_H] =RK(0, h);
278 key[KEY_I] =RK(0, i);
279 key[KEY_J] =RK(0, j);
280 key[KEY_K] =RK(0, k);
281 key[KEY_L] =RK(0, l);
282 key[KEY_M] =RK(0, m);
283 key[KEY_N] =RK(0, n);
284 key[KEY_O] =RK(0, o);
285 key[KEY_P] =RK(0, p);
286 key[KEY_Q] =RK(0, q);
287 key[KEY_R] =RK(0, r);
288 key[KEY_S] =RK(0, s);
289 key[KEY_T] =RK(0, t);
290 key[KEY_U] =RK(0, u);
291 key[KEY_V] =RK(0, v);
292 key[KEY_W] =RK(0, w);
293 key[KEY_X] =RK(0, x);
294 key[KEY_Y] =RK(0, y);
295 key[KEY_Z] =RK(0, z);
296 key[KEY_0] =RK(0, 0);
297 key[KEY_1] |=RK(0, 1);
298 key[KEY_2] |=RK(0, 2);
299 key[KEY_3] |=RK(0, 3);
300 key[KEY_4] |=RK(0, 4);
301 key[KEY_5] |=RK(0, 5);
302 key[KEY_6] |=RK(0, 6);
303 key[KEY_7] |=RK(0, 7);
304 key[KEY_8] |=RK(0, 8);
305 key[KEY_9] =RK(0, 9);
306 key[KEY_0_PAD] =RK(0, KP0);
307 key[KEY_1_PAD] =RK(0, KP1);
308 key[KEY_2_PAD] =RK(0, KP2);
309 key[KEY_3_PAD] =RK(0, KP3);
310 key[KEY_4_PAD] =RK(0, KP4);
311 key[KEY_5_PAD] =RK(0, KP5);
312 key[KEY_6_PAD] =RK(0, KP6);
313 key[KEY_7_PAD] =RK(0, KP7);
314 key[KEY_8_PAD] =RK(0, KP8);
315 key[KEY_9_PAD] =RK(0, KP9);
316 key[KEY_F1] =RK(0, F1);
317 key[KEY_F2] =RK(0, F2);
318 key[KEY_F3] =RK(0, F3);
319 key[KEY_F4] =RK(0, F4);
320 key[KEY_F5] =RK(0, F5);
321 key[KEY_F6] =RK(0, F6);
322 key[KEY_F7] =RK(0, F7);
323 key[KEY_F8] =RK(0, F8);
324 key[KEY_F9] =RK(0, F9);
325 key[KEY_F10] =RK(0, F10);
326 key[KEY_F11] =RK(0, F11);
327 key[KEY_F12] =RK(0, F12);
328 key[KEY_ESC] =RK(0, ESCAPE);
329 key[KEY_TILDE] =RK(0, TILDE);
330 key[KEY_MINUS] =RK(0, MINUS);
331 key[KEY_EQUALS] =RK(0, EQUALS);
332 key[KEY_BACKSPACE] =RK(0, BACKSPACE);
333 key[KEY_TAB] |=RK(0, TAB);
334 key[KEY_OPENBRACE] =RK(0, LEFTBRACKET);
335 key[KEY_CLOSEBRACE] =RK(0, RIGHTBRACKET);
336 key[KEY_ENTER] =RK(0, RETURN);
337 key[KEY_COLON] =RK(0, COLON);
338 key[KEY_QUOTE] =RK(0, QUOTE);
339 key[KEY_BACKSLASH] =RK(0, BACKSLASH);
340 key[KEY_BACKSLASH2] =RK(0, LESS);
341 key[KEY_COMMA] =RK(0, COMMA);
342 key[KEY_STOP] =RK(0, PERIOD);
343 key[KEY_SLASH] =RK(0, SLASH);
344 key[KEY_SPACE] =RK(0, SPACE);
345 key[KEY_INSERT] =RK(0, INSERT);
346 key[KEY_DEL] =RK(0, DELETE);
347 key[KEY_HOME] =RK(0, HOME);
348 key[KEY_END] =RK(0, END);
349 key[KEY_PGUP] =RK(0, PAGEUP);
350 key[KEY_PGDN] =RK(0, PAGEDOWN);
351 key[KEY_LEFT] =RK(0, LEFT);
352 key[KEY_RIGHT] =RK(0, RIGHT);
353 key[KEY_UP] =RK(0, UP);
354 key[KEY_DOWN] =RK(0, DOWN);
355 key[KEY_SLASH_PAD] =RK(0, KP_DIVIDE);
356 key[KEY_ASTERISK] =RK(0, ASTERISK);
357 key[KEY_MINUS_PAD] =RK(0, KP_MINUS);
358 key[KEY_PLUS_PAD] =RK(0, KP_PLUS);
359 key[KEY_DEL_PAD] =RK(0, KP_PERIOD);
360 key[KEY_ENTER_PAD] =RK(0, KP_ENTER);
361 key[KEY_PRTSCR] =RK(0, PRINT);
362 key[KEY_PAUSE] =RK(0, PAUSE);
363 key[KEY_LSHIFT] =RK(0, LSHIFT);
364 key[KEY_RSHIFT] =RK(0, RSHIFT);
365 key[KEY_LCONTROL] =RK(0, LCTRL);
366 key[KEY_RCONTROL] =RK(0, RCTRL);
367 key[KEY_ALT] =RK(0, LALT);
368 key[KEY_ALTGR] =RK(0, RALT);
369 key[KEY_LWIN] =RK(0, LMETA);
370 key[KEY_RWIN] =RK(0, RMETA);
371 key[KEY_MENU] =RK(0, MENU);
372 key[KEY_SCRLOCK] =RK(0, SCROLLOCK);
373 key[KEY_NUMLOCK] =RK(0, NUMLOCK);
374 key[KEY_CAPSLOCK] =RK(0, CAPSLOCK);
375
376 #undef RK
377 #undef JS
378 #undef _B
379 }
380
381 #ifdef WANT_LIBCO
hook_audio_done(void)382 void hook_audio_done(void)
383 {
384 }
385
hook_video_done(void)386 void hook_video_done(void)
387 {
388 co_switch(main_thread);
389 }
390
run_thread_proc(void)391 void run_thread_proc(void)
392 {
393 run_game(game_index);
394 hook_audio_done();
395 hook_video_done();
396 }
397 #else
hook_check(void)398 static void hook_check(void)
399 {
400 if (video_done && audio_done)
401 {
402 scond_signal(libretro_cond);
403 if (mame_sleep && !retro_hook_quit)
404 scond_wait(libretro_cond, libretro_mutex);
405 mame_sleep = 1;
406 }
407 }
408
hook_audio_done(void)409 void hook_audio_done(void)
410 {
411 slock_lock(libretro_mutex);
412 audio_done = 1;
413 hook_check();
414 slock_unlock(libretro_mutex);
415 }
416
hook_video_done(void)417 void hook_video_done(void)
418 {
419 slock_lock(libretro_mutex);
420 if (video_done) // Audio doesn't seem to be running atm, so fake it ...
421 audio_done = 1;
422 video_done = 1;
423 hook_check();
424 slock_unlock(libretro_mutex);
425 }
426
427 #ifdef WANT_LIBCO
run_thread_proc(void * v)428 void *run_thread_proc(void *v)
429 {
430 (void)v;
431
432 run_game(game_index);
433 thread_done = 1;
434 hook_audio_done();
435 hook_video_done();
436
437 return NULL;
438 }
439 #else
run_thread_proc(void * v)440 void run_thread_proc(void *v)
441 {
442 run_game(game_index);
443 thread_done = 1;
444 hook_audio_done();
445 hook_video_done();
446 }
447 #endif
448
lock_mame(void)449 static void lock_mame(void)
450 {
451 slock_lock(libretro_mutex);
452 while (!audio_done || !video_done)
453 scond_wait(libretro_cond, libretro_mutex);
454 slock_unlock(libretro_mutex);
455 }
456
unlock_mame(void)457 static void unlock_mame(void)
458 {
459 slock_lock(libretro_mutex);
460 mame_sleep = 0;
461 scond_signal(libretro_cond);
462 slock_unlock(libretro_mutex);
463 }
464 #endif
465
retro_init(void)466 void retro_init(void)
467 {
468 #ifdef _3DS
469 gp2x_screen15 = (unsigned short *) linearMemAlign(640 * 480 * 2, 0x80);
470 #else
471 gp2x_screen15 = (unsigned short *) malloc(640 * 480 * 2);
472 #endif
473 #ifndef WANT_LIBCO
474 libretro_cond = scond_new();
475 libretro_mutex = slock_new();
476 #endif
477 init_joy_list();
478 update_variables();
479
480 if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
481 libretro_supports_bitmasks = true;
482 }
483
retro_deinit(void)484 void retro_deinit(void)
485 {
486 free(IMAMEBASEPATH);
487 free(IMAMESAMPLEPATH);
488 #ifdef _3DS
489 linearFree(gp2x_screen15);
490 #else
491 free(gp2x_screen15);
492 #endif
493 #ifndef WANT_LIBCO
494 scond_free(libretro_cond);
495 slock_free(libretro_mutex);
496 #endif
497
498 libretro_supports_bitmasks = false;
499 }
500
retro_api_version(void)501 unsigned retro_api_version(void)
502 {
503 return RETRO_API_VERSION;
504 }
505
retro_set_controller_port_device(unsigned port,unsigned device)506 void retro_set_controller_port_device(unsigned port, unsigned device)
507 {
508 (void)port;
509 (void)device;
510 }
511
retro_get_system_info(struct retro_system_info * info)512 void retro_get_system_info(struct retro_system_info *info)
513 {
514 info->library_name = "MAME 2000";
515 #ifdef GIT_VERSION
516 info->library_version = "0.37b5" GIT_VERSION;
517 #else
518 info->library_version = build_version;
519 #endif
520 info->need_fullpath = true;
521 info->valid_extensions = "zip|ZIP";
522 info->block_extract = true;
523 }
524
retro_get_system_av_info(struct retro_system_av_info * info)525 void retro_get_system_av_info(struct retro_system_av_info *info)
526 {
527 #ifndef WANT_LIBCO
528 lock_mame();
529 #endif
530 struct retro_game_geometry g = {
531 Machine->drv->screen_width,
532 Machine->drv->screen_height,
533 Machine->drv->screen_width,
534 Machine->drv->screen_height,
535 ((float) Machine->drv->screen_width / Machine->drv->screen_height) * ((Machine->drv->video_attributes & VIDEO_PIXEL_ASPECT_RATIO_MASK) == VIDEO_PIXEL_ASPECT_RATIO_1_2 ? 0.5f : 1.0f)
536 };
537 struct retro_system_timing t = {
538 Machine->drv->frames_per_second,
539 32000.0
540 };
541 info->timing = t;
542 info->geometry = g;
543 }
544
retro_run(void)545 void retro_run(void)
546 {
547 int i, j;
548 #ifdef WANT_LIBCO
549 if(libco_quit==0)co_switch(core_thread);
550 else printf("running dead emulator");
551 #else
552 lock_mame();
553
554 // if (thread_done)
555 // environ_cb(RETRO_ENVIRONMENT_SHUTDOWN, NULL);
556 #endif
557
558 bool updated = false;
559
560 update_input();
561
562 if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
563 update_variables();
564
565 video_cb(gp2x_screen15, gfx_width, gfx_height, gfx_width * 2);
566 if (samples_per_frame)
567 {
568 if (usestereo)
569 audio_batch_cb(samples_buffer, samples_per_frame);
570 else
571 {
572 for (i = 0, j = 0; i < samples_per_frame; i++)
573 {
574 conversion_buffer[j++] = samples_buffer[i];
575 conversion_buffer[j++] = samples_buffer[i];
576 }
577 audio_batch_cb(conversion_buffer, samples_per_frame);
578 }
579 }
580
581 audio_done = 0;
582 video_done = 0;
583
584 #ifndef WANT_LIBCO
585 unlock_mame();
586 #endif
587 }
588
retro_load_game(const struct retro_game_info * info)589 bool retro_load_game(const struct retro_game_info *info)
590 {
591 struct retro_input_descriptor desc[] = {
592 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
593 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
594 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
595 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
596 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 1" },
597 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Button 2" },
598 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Button 4" },
599 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Button 3" },
600 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Button 5" },
601 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Button 6" },
602 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Coins" },
603 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
604 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "OSD Menu" },
605
606 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
607 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
608 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
609 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
610 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 1" },
611 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Button 2" },
612 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Button 4" },
613 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Button 3" },
614 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Button 5" },
615 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Button 6" },
616 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Coins" },
617 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
618 { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "OSD Menu" },
619
620 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
621 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
622 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
623 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
624 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 1" },
625 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Button 2" },
626 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Button 4" },
627 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Button 3" },
628 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Button 5" },
629 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Button 6" },
630 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Coins" },
631 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
632 { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "OSD Menu" },
633
634 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
635 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
636 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
637 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
638 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 1" },
639 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Button 2" },
640 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Button 4" },
641 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Button 3" },
642 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Button 5" },
643 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Button 6" },
644 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Coins" },
645 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
646 { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "OSD Menu" },
647
648 { 0, 0, 0, 0, NULL },
649 };
650
651 environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
652
653 enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
654 if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
655 {
656 fprintf(stderr, "[libretro]: RGB565 is not supported.\n");
657 return false;
658 }
659
660 retro_content_directory = strdup(info->path);
661 path_basedir(retro_content_directory);
662
663 printf("CONTENT_DIRECTORY: %s\n", retro_content_directory);
664
665 /* Get system directory from frontend */
666 retro_system_directory = NULL;
667 environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY,&retro_system_directory);
668 if (retro_system_directory == NULL || retro_system_directory[0] == '\0')
669 {
670 printf("libretro system path not set by frontend, using content path\n");
671 retro_system_directory = retro_content_directory;
672 }
673 printf("SYSTEM_DIRECTORY: %s\n", retro_system_directory);
674
675
676 /* Get save directory from frontend */
677 retro_save_directory = NULL;
678 environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY,&retro_save_directory);
679 if (retro_save_directory == NULL || retro_save_directory[0] == '\0')
680 {
681 printf("libretro save path not set by frontent, using content path\n");
682 retro_save_directory = retro_content_directory;
683 }
684 printf("SAVE_DIRECTORY: %s\n", retro_save_directory);
685
686 sprintf(core_sys_directory,"%s%cmame2000\0",retro_system_directory,slash);
687 sprintf(core_save_directory,"%s%cmame2000\0",retro_save_directory,slash);
688 printf("MAME2000_SYS_DIRECTORY: %s\n", core_sys_directory);
689 printf("MAME2000_SAVE_DIRECTORY: %s\n", core_save_directory);
690
691 IMAMEBASEPATH = (char *) malloc(1024);
692 IMAMESAMPLEPATH = (char *) malloc(1024);
693
694
695 int i;
696 memcpy(IMAMEBASEPATH, info->path, strlen(info->path) + 1);
697 if (strrchr(IMAMEBASEPATH, slash)) *(strrchr(IMAMEBASEPATH, slash)) = 0;
698 else { IMAMEBASEPATH[0] = '.'; IMAMEBASEPATH[1] = 0; }
699 char baseName[1024];
700 const char *romName = info->path;
701 if (strrchr(info->path, slash)) romName = strrchr(info->path, slash) + 1;
702 memcpy(baseName, romName, strlen(romName) + 1);
703 if (strrchr(baseName, '.')) *(strrchr(baseName, '.')) = 0;
704
705 strcpy(IMAMESAMPLEPATH, IMAMEBASEPATH);
706 strcat(IMAMESAMPLEPATH, "/samples");
707
708 /* do we have a driver for this? */
709 for (i = 0; drivers[i] && (game_index == -1); i++)
710 {
711 if (strcasecmp(baseName,drivers[i]->name) == 0)
712 {
713 game_index = i;
714 break;
715 }
716 }
717
718 if (game_index == -1)
719 {
720 printf("Game \"%s\" not supported\n", baseName);
721 return false;
722 }
723
724 /* parse generic (os-independent) options */
725 //parse_cmdline (argc, argv, game_index);
726
727 //Set default path
728 nvdir=(char *) malloc(1024);sprintf(nvdir,"%s%c%s\0",core_save_directory,slash,"nvram");
729 i=create_path_recursive(nvdir);
730 if(i!=0)printf("error %d creating nvram \"%s\"\n", i,nvdir);
731
732 hidir=(char *) malloc(1024);sprintf(hidir,"%s%c%s\0",core_save_directory,slash,"hi");
733 i=create_path_recursive(hidir);
734 if(i!=0)printf("error %d creating hi \"%s\"\n", i,hidir);
735
736 cfgdir=(char *) malloc(1024);sprintf(cfgdir,"%s%c%s\0",core_save_directory,slash,"cfg");
737 i=create_path_recursive(cfgdir);
738 if(i!=0)printf("error %d creating cfg \"%s\"\n", i,cfgdir);
739
740 screenshotdir=(char *) malloc(1024);sprintf(screenshotdir,"%s%c%s\0",core_save_directory,slash,"snap");
741 i=create_path_recursive(screenshotdir);
742 if(i!=0)printf("error %d creating snap \"%s\"\n", i,screenshotdir);
743
744 memcarddir=(char *) malloc(1024);sprintf(memcarddir,"%s%c%s\0",core_save_directory,slash,"memcard");
745 i=create_path_recursive(memcarddir);
746 if(i!=0)printf("error %d creating memcard \"%s\"\n", i,memcarddir);
747
748 stadir=(char *) malloc(1024);sprintf(stadir,"%s%c%s\0",core_sys_directory,slash,"sta");
749 i=create_path_recursive(stadir);
750 if(i!=0)printf("error %d creating sta \"%s\"\n", i,stadir);
751
752 artworkdir=(char *) malloc(1024);sprintf(artworkdir,"%s%c%s\0",core_sys_directory,slash,"artwork");
753 i=create_path_recursive(artworkdir);
754 if(i!=0)printf("error %d creating artwork \"%s\"\n", i,artworkdir);
755
756 cheatdir=(char *) malloc(1024);sprintf(cheatdir,"%s%c%s\0",core_sys_directory,slash,"cheat");
757 i=create_path_recursive(cheatdir);
758 if(i!=0)printf("error %d creating cheat \"%s\"\n", i,cheatdir);
759
760 Machine->sample_rate = 32000;
761 options.samplerate = 32000;
762
763 /* This is needed so emulated YM3526/YM3812 chips are used instead on physical ones. */
764 options.use_emulated_ym3812 = 1;
765
766 /* enable samples - should be stored in "sample" subdirectory from roms */
767 options.use_samples = 1;
768
769 /* skip disclaimer - skips 'nag screen' */
770 options.skip_disclaimer = skip_disclaimer;
771
772 #if (HAS_CYCLONE || HAS_DRZ80)
773 int use_cyclone = 1;
774 int use_drz80 = 1;
775 int use_drz80_snd = 1;
776
777 for (i=0;i<NUMGAMES;i++)
778 {
779 if (strcmp(drivers[game_index]->name,fe_drivers[i].name)==0)
780 {
781 /* ASM cores: 0=None,1=Cyclone,2=DrZ80,3=Cyclone+DrZ80,4=DrZ80(snd),5=Cyclone+DrZ80(snd) */
782 switch (fe_drivers[i].cores)
783 {
784 case 0:
785 use_cyclone = 0;
786 use_drz80_snd = 0;
787 use_drz80 = 0;
788 break;
789 case 1:
790 use_drz80_snd = 0;
791 use_drz80 = 0;
792 break;
793 case 2:
794 use_cyclone = 0;
795 break;
796 case 4:
797 use_cyclone = 0;
798 use_drz80 = 0;
799 break;
800 case 5:
801 use_drz80 = 0;
802 break;
803 default:
804 break;
805 }
806
807 break;
808 }
809 }
810
811 /* Replace M68000 by CYCLONE */
812 #if (HAS_CYCLONE)
813 if (use_cyclone)
814 {
815 for (i=0;i<MAX_CPU;i++)
816 {
817 int *type=(int*)&(drivers[game_index]->drv->cpu[i].cpu_type);
818 #ifdef NEOMAME
819 if (((*type)&0xff)==CPU_M68000)
820 #else
821 if (((*type)&0xff)==CPU_M68000 || ((*type)&0xff)==CPU_M68010 )
822 #endif
823 {
824 *type=((*type)&(~0xff))|CPU_CYCLONE;
825 }
826 }
827 }
828 #endif
829
830 #if (HAS_DRZ80)
831 /* Replace Z80 by DRZ80 */
832 if (use_drz80)
833 {
834 for (i=0;i<MAX_CPU;i++)
835 {
836 int *type=(int*)&(drivers[game_index]->drv->cpu[i].cpu_type);
837 if (((*type)&0xff)==CPU_Z80)
838 {
839 *type=((*type)&(~0xff))|CPU_DRZ80;
840 }
841 }
842 }
843
844 /* Replace Z80 with DRZ80 only for sound CPUs */
845 if (use_drz80_snd)
846 {
847 for (i=0;i<MAX_CPU;i++)
848 {
849 int *type=(int*)&(drivers[game_index]->drv->cpu[i].cpu_type);
850 if ((((*type)&0xff)==CPU_Z80) && ((*type)&CPU_AUDIO_CPU))
851 {
852 *type=((*type)&(~0xff))|CPU_DRZ80;
853 }
854 }
855 }
856 #endif
857
858 #endif
859
860 // Remove the mouse usage for certain games
861 if ( (strcasecmp(drivers[game_index]->name,"hbarrel")==0) || (strcasecmp(drivers[game_index]->name,"hbarrelw")==0) ||
862 (strcasecmp(drivers[game_index]->name,"midres")==0) || (strcasecmp(drivers[game_index]->name,"midresu")==0) ||
863 (strcasecmp(drivers[game_index]->name,"midresj")==0) || (strcasecmp(drivers[game_index]->name,"tnk3")==0) ||
864 (strcasecmp(drivers[game_index]->name,"tnk3j")==0) || (strcasecmp(drivers[game_index]->name,"ikari")==0) ||
865 (strcasecmp(drivers[game_index]->name,"ikarijp")==0) || (strcasecmp(drivers[game_index]->name,"ikarijpb")==0) ||
866 (strcasecmp(drivers[game_index]->name,"victroad")==0) || (strcasecmp(drivers[game_index]->name,"dogosoke")==0) ||
867 (strcasecmp(drivers[game_index]->name,"gwar")==0) || (strcasecmp(drivers[game_index]->name,"gwarj")==0) ||
868 (strcasecmp(drivers[game_index]->name,"gwara")==0) || (strcasecmp(drivers[game_index]->name,"gwarb")==0) ||
869 (strcasecmp(drivers[game_index]->name,"bermudat")==0) || (strcasecmp(drivers[game_index]->name,"bermudaj")==0) ||
870 (strcasecmp(drivers[game_index]->name,"bermudaa")==0) || (strcasecmp(drivers[game_index]->name,"mplanets")==0) ||
871 (strcasecmp(drivers[game_index]->name,"forgottn")==0) || (strcasecmp(drivers[game_index]->name,"lostwrld")==0) ||
872 (strcasecmp(drivers[game_index]->name,"gondo")==0) || (strcasecmp(drivers[game_index]->name,"makyosen")==0) ||
873 (strcasecmp(drivers[game_index]->name,"topgunr")==0) || (strcasecmp(drivers[game_index]->name,"topgunbl")==0) ||
874 (strcasecmp(drivers[game_index]->name,"tron")==0) || (strcasecmp(drivers[game_index]->name,"tron2")==0) ||
875 (strcasecmp(drivers[game_index]->name,"kroozr")==0) ||(strcasecmp(drivers[game_index]->name,"crater")==0) ||
876 (strcasecmp(drivers[game_index]->name,"dotron")==0) || (strcasecmp(drivers[game_index]->name,"dotrone")==0) ||
877 (strcasecmp(drivers[game_index]->name,"zwackery")==0) || (strcasecmp(drivers[game_index]->name,"ikari3")==0) ||
878 (strcasecmp(drivers[game_index]->name,"searchar")==0) || (strcasecmp(drivers[game_index]->name,"sercharu")==0) ||
879 (strcasecmp(drivers[game_index]->name,"timesold")==0) || (strcasecmp(drivers[game_index]->name,"timesol1")==0) ||
880 (strcasecmp(drivers[game_index]->name,"btlfield")==0) || (strcasecmp(drivers[game_index]->name,"aztarac")==0))
881 {
882 extern int use_mouse;
883 use_mouse=0;
884 }
885
886 decompose_rom_sample_path(IMAMEBASEPATH, IMAMESAMPLEPATH);
887
888 mame_sleep = 1;
889
890 #ifdef WANT_LIBCO
891 main_thread = co_active();
892 core_thread = co_create(0x10000, run_thread_proc);
893 co_switch(core_thread);
894 #else
895 run_thread = sthread_create(run_thread_proc, NULL);
896 #endif
897
898 return true;
899 }
900
retro_unload_game(void)901 void retro_unload_game(void)
902 {
903 #ifdef WANT_LIBCO
904 if(libco_quit==0){
905 printf("ask for quit!\n");
906 libco_quit=1;
907 co_switch(core_thread);
908 }
909 else printf("esc pressed quit!\n");
910 co_delete(core_thread);
911 #else
912 slock_lock(libretro_mutex);
913 // make sure we escape the copyright warning and game warning loops
914 key[KEY_ESC] = 1;
915 retro_hook_quit = 1;
916 mame_sleep = 0;
917 scond_signal(libretro_cond);
918 slock_unlock(libretro_mutex);
919
920 if (run_thread)
921 sthread_join(run_thread);
922
923 run_thread = NULL;
924 retro_hook_quit = 0;
925 #endif
926 }
927
retro_get_region(void)928 unsigned retro_get_region(void)
929 {
930 return RETRO_REGION_NTSC;
931 }
932
retro_load_game_special(unsigned type,const struct retro_game_info * info,size_t num)933 bool retro_load_game_special(unsigned type, const struct retro_game_info *info, size_t num)
934 {
935 (void)type;
936 (void)info;
937 (void)num;
938 return false;
939 }
940
retro_serialize_size(void)941 size_t retro_serialize_size(void)
942 {
943 return 0;
944 }
945
retro_serialize(void * data_,size_t size)946 bool retro_serialize(void *data_, size_t size)
947 {
948 (void)data_;
949 (void)size;
950 return false;
951 }
952
retro_unserialize(const void * data_,size_t size)953 bool retro_unserialize(const void *data_, size_t size)
954 {
955 (void)data_;
956 (void)size;
957 return false;
958 }
959
retro_get_memory_data(unsigned id)960 void *retro_get_memory_data(unsigned id)
961 {
962 return NULL;
963 }
964
retro_get_memory_size(unsigned id)965 size_t retro_get_memory_size(unsigned id)
966 {
967 return 0;
968 }
969
retro_cheat_reset(void)970 void retro_cheat_reset(void)
971 {}
972
retro_cheat_set(unsigned index,bool enabled,const char * code)973 void retro_cheat_set(unsigned index, bool enabled, const char *code)
974 {
975 (void)index;
976 (void)enabled;
977 (void)code;
978 }
979