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