1 /*********************************************************************
2 
3 	mame2003.c
4 
5     a port of Xmame 0.78 to the libretro API
6 
7 *********************************************************************/
8 
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <string/stdstring.h>
12 #include <libretro.h>
13 #include <file/file_path.h>
14 #include <math.h>
15 #include <string.h>
16 
17 #if (HAS_DRZ80 || HAS_CYCLONE)
18 #include "frontend_list.h"
19 #endif
20 
21 #include "mame.h"
22 #include "driver.h"
23 #include "state.h"
24 #include "log.h"
25 #include "input.h"
26 #include "inptport.h"
27 #include "fileio.h"
28 #include "controls.h"
29 #include "usrintrf.h"
30 
31 int  pressure_check =  1.28 * 20;
32 int convert_analog_scale(int input);
33 
34 int gotFrame;
35 static const struct GameDriver  *game_driver;
36 static float              delta_samples;
37 int                       samples_per_frame = 0;
38 int                       orig_samples_per_frame =0;
39 short*                    samples_buffer;
40 short*                    conversion_buffer;
41 int                       usestereo = 1;
42 int16_t                   prev_pointer_x;
43 int16_t                   prev_pointer_y;
44 unsigned                  retroColorMode;
45 unsigned long             lastled = 0;
46 
47 extern const struct KeyboardInfo retroKeys[];
48 extern int          retroKeyState[512];
49 int                 retroJsState[109]= {0}; // initialise to zero - we are only reading 4 players atm
50 extern int16_t      mouse_x[4];
51 extern int16_t      mouse_y[4];
52 extern int16_t      analogjoy[4][4];
53 struct ipd          *default_inputs; /* pointer the array of structs with default MAME input mappings and labels */
54 
55 static struct retro_input_descriptor empty[] = { { 0 } };
56 
57 retro_log_printf_t                 log_cb;
58 static struct retro_message        frontend_message;
59 
60 struct                             retro_perf_callback perf_cb;
61 retro_environment_t                environ_cb                    = NULL;
62 retro_video_refresh_t              video_cb                      = NULL;
63 static retro_input_poll_t          poll_cb                       = NULL;
64 static retro_input_state_t         input_cb                      = NULL;
65 static retro_audio_sample_batch_t  audio_batch_cb                = NULL;
66 retro_set_led_state_t              led_state_cb                  = NULL;
67 
68 bool old_dual_joystick_state = false; /* used to track when this core option changes */
69 
70 /******************************************************************************
71 
72 Core options
73 
74 ******************************************************************************/
75 
76 enum CORE_OPTIONS/* controls the order in which core options appear. common, important, and content-specific options should go earlier on the list */
77 {
78   OPT_4WAY = 0,
79   OPT_MOUSE_DEVICE,
80   OPT_CROSSHAIR_ENABLED,
81   OPT_SKIP_DISCLAIMER,
82   OPT_SKIP_WARNINGS,
83   OPT_DISPLAY_SETUP,
84   OPT_NEOGEO_BIOS,
85   OPT_STV_BIOS,
86   OPT_USE_ALT_SOUND,
87   OPT_SHARE_DIAL,
88   OPT_DUAL_JOY,
89   OPT_RSTICK_BTNS,
90   OPT_VECTOR_RESOLUTION,
91   OPT_VECTOR_ANTIALIAS,
92   OPT_VECTOR_BEAM,
93   OPT_VECTOR_TRANSLUCENCY,
94   OPT_VECTOR_FLICKER,
95   OPT_VECTOR_INTENSITY,
96   OPT_DCS_SPEEDHACK,
97   OPT_CORE_SYS_SUBFOLDER,
98   OPT_CORE_SAVE_SUBFOLDER,
99   OPT_TATE_MODE,
100   OPT_BRIGHTNESS,
101   OPT_GAMMA,
102   OPT_FRAMESKIP,
103   OPT_SAMPLE_RATE,
104   OPT_INPUT_INTERFACE,
105   OPT_MAME_REMAPPING,
106   OPT_ARTWORK,
107   OPT_ART_RESOLUTION,
108   OPT_NVRAM_BOOTSTRAP,
109   OPT_Cheat_Input_Ports,
110   OPT_Machine_Timing,
111   OPT_end /* dummy last entry */
112 };
113 
114 static struct retro_variable_default  default_options[OPT_end + 1];    /* need the plus one for the NULL entries at the end */
115 static struct retro_variable          current_options[OPT_end + 1];
116 
117 
118 /******************************************************************************
119 
120   private function prototypes
121 
122 ******************************************************************************/
123 static void   set_content_flags(void);
124 static void   init_core_options(void);
125        void   init_default(struct retro_variable_default *option, const char *key, const char *value);
126 static void   update_variables(bool first_time);
127 static void   set_variables(bool first_time);
128 static struct retro_variable_default *spawn_effective_option(int option_index);
129 static void   check_system_specs(void);
130        void   retro_describe_controls(void);
131        int    get_mame_ctrl_id(int display_idx, int retro_ID);
132 
133 
134 /******************************************************************************
135 
136 	frontend message interface
137 
138 ******************************************************************************/
frontend_message_cb(const char * message_string,unsigned frames_to_display)139 void frontend_message_cb(const char *message_string, unsigned frames_to_display)
140 {
141   frontend_message.msg    = message_string;
142   frontend_message.frames = frames_to_display;
143   environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &frontend_message);
144 }
145 
146 /******************************************************************************
147 
148   implementation of key libretro functions
149 
150 ******************************************************************************/
151 
retro_init(void)152 void retro_init (void)
153 {
154   struct retro_log_callback log;
155   if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
156     log_cb = log.log;
157   else
158     log_cb = NULL;
159 
160 #ifdef LOG_PERFORMANCE
161   environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb);
162 #endif
163 
164   check_system_specs();
165 }
166 
check_system_specs(void)167 static void check_system_specs(void)
168 {
169    /* Should we set level variably like the API asks? Are there any frontends that implement this? */
170    unsigned level = 10; /* For stub purposes, set to the highest level */
171    environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level);
172 }
173 
retro_set_environment(retro_environment_t cb)174 void retro_set_environment(retro_environment_t cb)
175 {
176   environ_cb = cb;
177 }
178 
179 
180 /* static void init_core_options(void)
181  *
182  * Note that core options are not presented in order they are initialized here,
183  * but rather by their order in the OPT_ enum
184  */
init_core_options(void)185 static void init_core_options(void)
186 {
187   init_default(&default_options[OPT_4WAY],                APPNAME"_four_way_emulation",  "4-way joystick emulation on 8-way joysticks; disabled|enabled");
188 #if defined(__IOS__)
189   init_default(&default_options[OPT_MOUSE_DEVICE],        APPNAME"_mouse_device",        "Mouse Device; pointer|mouse|disabled");
190 #else
191   init_default(&default_options[OPT_MOUSE_DEVICE],        APPNAME"_mouse_device",        "Mouse Device; mouse|pointer|disabled");
192 #endif
193   init_default(&default_options[OPT_CROSSHAIR_ENABLED],   APPNAME"_crosshair_enabled",   "Show Lightgun crosshair; enabled|disabled");
194   init_default(&default_options[OPT_SKIP_DISCLAIMER],     APPNAME"_skip_disclaimer",     "Skip Disclaimer; disabled|enabled");
195   init_default(&default_options[OPT_SKIP_WARNINGS],       APPNAME"_skip_warnings",       "Skip Warnings; disabled|enabled");
196   init_default(&default_options[OPT_DISPLAY_SETUP],       APPNAME"_display_setup",       "Display MAME menu; disabled|enabled");
197   init_default(&default_options[OPT_BRIGHTNESS],          APPNAME"_brightness",          "Brightness; 1.0|0.2|0.3|0.4|0.5|0.6|0.7|0.8|0.9|1.1|1.2|1.3|1.4|1.5|1.6|1.7|1.8|1.9|2.0");
198   init_default(&default_options[OPT_GAMMA],               APPNAME"_gamma",               "Gamma correction; 1.0|0.5|0.6|0.7|0.8|0.9|1.1|1.2|1.3|1.4|1.5|1.6|1.7|1.8|1.9|2.0");
199   init_default(&default_options[OPT_ARTWORK],             APPNAME"_display_artwork",     "Display artwork (Restart core); enabled|disabled");
200   init_default(&default_options[OPT_ART_RESOLUTION],      APPNAME"_art_resolution",      "Artwork resolution multiplier (Restart core); 1|2");
201   init_default(&default_options[OPT_NEOGEO_BIOS],         APPNAME"_neogeo_bios",         "Specify Neo Geo BIOS (Restart core); default|euro|euro-s1|us|us-e|asia|japan|japan-s2|unibios33|unibios20|unibios13|unibios11|unibios10|debug|asia-aes");
202   init_default(&default_options[OPT_STV_BIOS],            APPNAME"_stv_bios",            "Specify Sega ST-V BIOS (Restart core); default|japan|japana|us|japan_b|taiwan|europe");
203   init_default(&default_options[OPT_USE_ALT_SOUND],       APPNAME"_use_alt_sound",       "Use CD soundtrack (Restart core); disabled");
204   init_default(&default_options[OPT_SHARE_DIAL],          APPNAME"_dialsharexy",         "Share 2 player dial controls across one X/Y device; disabled|enabled");
205   init_default(&default_options[OPT_DUAL_JOY],            APPNAME"_dual_joysticks",      "Dual joystick mode (!NETPLAY); disabled|enabled");
206   init_default(&default_options[OPT_RSTICK_BTNS],         APPNAME"_rstick_to_btns",      "Map right analog stick as buttons; enabled|disabled");
207   init_default(&default_options[OPT_TATE_MODE],           APPNAME"_tate_mode",           "TATE Mode - Rotating display (Restart core); disabled|enabled");
208   init_default(&default_options[OPT_VECTOR_RESOLUTION],   APPNAME"_vector_resolution",   "Vector resolution (Restart core); 1024x768|640x480|1280x960|1440x1080|1600x1200|original");
209   init_default(&default_options[OPT_VECTOR_ANTIALIAS],    APPNAME"_vector_antialias",    "Vector antialiasing; enabled|disabled");
210   init_default(&default_options[OPT_VECTOR_BEAM],         APPNAME"_vector_beam_width",   "Vector beam width (only with antialiasing); 1.2|1|1.4|1.6|1.8|2|2.5|3|4|5|6|7|8|9|10|11|12");
211   init_default(&default_options[OPT_VECTOR_TRANSLUCENCY], APPNAME"_vector_translucency", "Vector translucency; enabled|disabled");
212   init_default(&default_options[OPT_VECTOR_FLICKER],      APPNAME"_vector_flicker",      "Vector flicker; 20|0|10|30|40|50|60|70|80|90|100");
213   init_default(&default_options[OPT_VECTOR_INTENSITY],    APPNAME"_vector_intensity",    "Vector intensity; 1.5|0.5|1|2|2.5|3");
214   init_default(&default_options[OPT_NVRAM_BOOTSTRAP],     APPNAME"_nvram_bootstraps",    "NVRAM Bootstraps; enabled|disabled");
215   init_default(&default_options[OPT_SAMPLE_RATE],         APPNAME"_sample_rate",         "Sample Rate (KHz); 48000|8000|11025|22050|30000|44100|");
216   init_default(&default_options[OPT_DCS_SPEEDHACK],       APPNAME"_dcs_speedhack",       "DCS Speedhack; enabled|disabled");
217   init_default(&default_options[OPT_INPUT_INTERFACE],     APPNAME"_input_interface",     "Input interface; simultaneous|retropad|keyboard");
218   init_default(&default_options[OPT_MAME_REMAPPING],      APPNAME"_mame_remapping",      "Legacy Remapping (!NETPLAY); enabled|disabled");
219   init_default(&default_options[OPT_FRAMESKIP],           APPNAME"_frameskip",           "Frameskip; 0|1|2|3|4|5");
220   init_default(&default_options[OPT_CORE_SYS_SUBFOLDER],  APPNAME"_core_sys_subfolder",  "Locate system files within a subfolder; enabled|disabled"); /* This should be probably handled by the frontend and not by cores per discussions in Fall 2018 but RetroArch for example doesn't provide this as an option. */
221   init_default(&default_options[OPT_CORE_SAVE_SUBFOLDER], APPNAME"_core_save_subfolder", "Locate save files within a subfolder; enabled|disabled"); /* This is already available as an option in RetroArch although it is left enabled by default as of November 2018 for consistency with past practice. At least for now.*/
222   init_default(&default_options[OPT_Cheat_Input_Ports],   APPNAME"_cheat_input_ports",   "Dip switch/Cheat input ports; disabled|enabled");
223   init_default(&default_options[OPT_Machine_Timing],      APPNAME"_machine_timing",      "Bypass Timing Skew (Restart core); disabled|enabled");
224   init_default(&default_options[OPT_end], NULL, NULL);
225   set_variables(true);
226 }
227 
set_variables(bool first_time)228 static void set_variables(bool first_time)
229 {
230   static struct retro_variable_default  effective_defaults[OPT_end + 1];
231   static unsigned effective_options_count;         /* the number of core options in effect for the current content */
232   int option_index   = 0;
233 
234   for(option_index = 0; option_index < (OPT_end + 1); option_index++)
235   {
236     switch(option_index)
237     {
238       case OPT_4WAY:
239          if(options.content_flags[CONTENT_JOYSTICK_DIRECTIONS] != 4)
240            continue;
241          break;
242       case OPT_CROSSHAIR_ENABLED:
243          if(!options.content_flags[CONTENT_LIGHTGUN])
244            continue;
245          break;
246       case OPT_STV_BIOS:
247          if(!options.content_flags[CONTENT_STV])
248            continue; /* only offer BIOS selection when it is relevant */
249          break;
250       case OPT_NEOGEO_BIOS:
251           if(!options.content_flags[CONTENT_NEOGEO])
252             continue; /* only offer BIOS selection when it is relevant */
253           break;
254       case OPT_USE_ALT_SOUND:
255          /*if(!options.content_flags[CONTENT_ALT_SOUND])*/
256            continue;
257          break;
258       case OPT_SHARE_DIAL:
259          if(!options.content_flags[CONTENT_DIAL])
260            continue;
261          break;
262       case OPT_DUAL_JOY:
263          if(!options.content_flags[CONTENT_DUAL_JOYSTICK])
264            continue;
265          break;
266       case OPT_VECTOR_RESOLUTION:
267       case OPT_VECTOR_ANTIALIAS:
268       case OPT_VECTOR_TRANSLUCENCY:
269       case OPT_VECTOR_BEAM:
270       case OPT_VECTOR_FLICKER:
271       case OPT_VECTOR_INTENSITY:
272          if(!options.content_flags[CONTENT_VECTOR])
273            continue;
274          break;
275       case OPT_DCS_SPEEDHACK:
276          if(!options.content_flags[CONTENT_DCS_SPEEDHACK])
277            continue;
278          break;
279       case OPT_NVRAM_BOOTSTRAP:
280          if(!options.content_flags[CONTENT_NVRAM_BOOTSTRAP])
281            continue;
282          break;
283       case OPT_Machine_Timing:
284          continue;
285    }
286    effective_defaults[effective_options_count] = first_time ? default_options[option_index] : *spawn_effective_option(option_index);
287    effective_options_count++;
288   }
289 
290   environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)effective_defaults);
291 
292 }
293 
spawn_effective_option(int option_index)294 static struct retro_variable_default *spawn_effective_option(int option_index)
295 {
296   static struct retro_variable_default *encoded_option = NULL;
297 
298   /* implementing this function will allow the core to change a core option within the core and then report that that change to the frontend
299    * currently core options only flow one way: from the frontend to mame2003-plus
300    *
301    * search for the string "; " as the delimiter between the option display name and the values
302    * stringify the current value for this option
303    * see if the current option string is already listed first in the original default --
304    *    if the current selected option is not in the original defaults string at all
305    *      log an error message and bail. that shouldn't be possible.
306    *    is the currently selected option the first in the default pipe-delimited list?
307    *      if so, just return default_options[option_index]
308    *    else
309    *       create a copy of default_options[option_index].defaults_string.
310    *       First add the stringified current option as the first in the pipe-delimited list for this copied string
311    *       then remove the option from wherever it was originally in the defaults string
312    */
313   return encoded_option;
314 }
315 
init_default(struct retro_variable_default * def,const char * key,const char * label_and_values)316 void init_default(struct retro_variable_default *def, const char *key, const char *label_and_values)
317 {
318   def->key = key;
319   def->defaults_string = label_and_values;
320 }
321 
update_variables(bool first_time)322 static void update_variables(bool first_time)
323 {
324   struct retro_led_interface ledintf;
325   struct retro_variable var;
326   int index;
327   bool reset_control_descriptions = false;
328 
329   for(index = 0; index < OPT_end; index++)
330   {
331     var.value = NULL;
332     var.key = default_options[index].key;
333     if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && !string_is_empty(var.value)) /* the frontend sends a value for this core option */
334     {
335       current_options[index].value = var.value; /* keep the state of core options matched with the frontend */
336 
337       switch(index)
338       {
339         case OPT_INPUT_INTERFACE:
340           if(strcmp(var.value, "retropad") == 0)
341             options.input_interface = RETRO_DEVICE_JOYPAD;
342           else if(strcmp(var.value, "keyboard") == 0)
343             options.input_interface = RETRO_DEVICE_KEYBOARD;
344 		    else
345 			    options.input_interface = RETRO_DEVICE_KEYBOARD + RETRO_DEVICE_JOYPAD;
346         break;
347 
348         case OPT_4WAY:
349           if( (strcmp(var.value, "enabled") == 0) && (options.content_flags[CONTENT_JOYSTICK_DIRECTIONS] == 4) )
350           {
351             if(!options.restrict_4_way)           /* the option has just been toggled to "enabled" */
352             {
353               options.restrict_4_way = true;
354               reset_control_descriptions = true;  /* games with rotated joysticks send different control descriptions in 4-way restrictor mode */
355             }
356           }
357           else
358           {
359             if(options.restrict_4_way)            /* the option has just been toggled to "disabled" */
360             {
361               options.restrict_4_way = false;
362               reset_control_descriptions = true;  /* games with rotated joysticks send different control descriptions in 4-way restrictor mode */
363             }
364           }
365           break;
366 
367         case OPT_MOUSE_DEVICE:
368           if(strcmp(var.value, "pointer") == 0)
369             options.mouse_device = RETRO_DEVICE_POINTER;
370           else if(strcmp(var.value, "mouse") == 0)
371             options.mouse_device = RETRO_DEVICE_MOUSE;
372           else
373             options.mouse_device = 0;
374           break;
375 
376         case OPT_CROSSHAIR_ENABLED:
377           if(strcmp(var.value, "enabled") == 0)
378             options.crosshair_enable = 1;
379           else
380             options.crosshair_enable = 0;
381           break;
382 
383         case OPT_SKIP_DISCLAIMER:
384           if(strcmp(var.value, "enabled") == 0)
385             options.skip_disclaimer = true;
386           else
387             options.skip_disclaimer = false;
388           break;
389 
390         case OPT_SKIP_WARNINGS:
391           if(strcmp(var.value, "enabled") == 0)
392             options.skip_warnings = true;
393           else
394             options.skip_warnings = false;
395           break;
396 
397         case OPT_DISPLAY_SETUP:
398           if(strcmp(var.value, "enabled") == 0)
399             options.display_setup = 1;
400           else
401             options.display_setup = 0;
402           break;
403 
404         case OPT_BRIGHTNESS:
405           options.brightness = atof(var.value);
406           if(!first_time)
407             palette_set_global_brightness(options.brightness);
408           break;
409 
410         case OPT_GAMMA:
411           options.gamma = atof(var.value);
412           if(!first_time)
413             palette_set_global_gamma(options.gamma);
414           break;
415 
416           /* TODO: Add overclock option. Below is the code from the old MAME osd to help process the core option.*/
417           /*
418 
419           double overclock;
420           int cpu, doallcpus = 0, oc;
421 
422           if (code_pressed(KEYCODE_LSHIFT) || code_pressed(KEYCODE_RSHIFT))
423             doallcpus = 1;
424           if (!code_pressed(KEYCODE_LCONTROL) && !code_pressed(KEYCODE_RCONTROL))
425             increment *= 5;
426           if( increment :
427             overclock = timer_get_overclock(arg);
428             overclock += 0.01 * increment;
429             if (overclock < 0.01) overclock = 0.01;
430             if (overclock > 2.0) overclock = 2.0;
431             if( doallcpus )
432               for( cpu = 0; cpu < cpu_gettotalcpu(); cpu++ )
433                 timer_set_overclock(cpu, overclock);
434             else
435               timer_set_overclock(arg, overclock);
436           }
437 
438           oc = 100 * timer_get_overclock(arg) + 0.5;
439 
440           if( doallcpus )
441             sprintf(buf,"%s %s %3d%%", ui_getstring (UI_allcpus), ui_getstring (UI_overclock), oc);
442           else
443             sprintf(buf,"%s %s%d %3d%%", ui_getstring (UI_overclock), ui_getstring (UI_cpu), arg, oc);
444           displayosd(bitmap,buf,oc/2,100/2);
445         */
446 
447         case OPT_ARTWORK:
448           if(strcmp(var.value, "enabled") == 0)
449             options.use_artwork = ARTWORK_USE_ALL;
450           else
451             options.use_artwork = ARTWORK_USE_NONE;
452           break;
453 
454         case OPT_ART_RESOLUTION:
455           options.artwork_res = atoi(var.value);
456           break;
457 
458         case OPT_STV_BIOS:
459           if(!options.content_flags[CONTENT_STV])
460             break;
461           if(options.content_flags[CONTENT_DIEHARD]) /* catch required bios for this one game. */
462             options.bios = "us";
463           else
464             options.bios = (strcmp(var.value, "default") == 0) ? NULL : var.value;
465           break;
466 
467         case OPT_NEOGEO_BIOS:
468           if(!options.content_flags[CONTENT_NEOGEO])
469             break;
470           options.bios = (strcmp(var.value, "default") == 0) ? NULL : var.value;
471           break;
472 
473         case OPT_USE_ALT_SOUND:
474           if(options.content_flags[CONTENT_ALT_SOUND])
475           {
476             if(strcmp(var.value, "enabled") == 0)
477               options.use_samples = true;
478             else
479               options.use_samples = false;
480           }
481           break;
482 
483         case OPT_SHARE_DIAL:
484           if(options.content_flags[CONTENT_DIAL])
485           {
486             if(strcmp(var.value, "enabled") == 0)
487               options.dial_share_xy = 1;
488             else
489               options.dial_share_xy = 0;
490             break;
491           }
492           else
493           {
494             options.dial_share_xy = 0;
495             break;
496           }
497 
498         case OPT_DUAL_JOY:
499           if(options.content_flags[CONTENT_DUAL_JOYSTICK])
500           {
501             if(strcmp(var.value, "enabled") == 0)
502               options.dual_joysticks = true;
503             else
504               options.dual_joysticks = false;
505 
506             if(first_time)
507               old_dual_joystick_state = options.dual_joysticks;
508             else if(old_dual_joystick_state != options.dual_joysticks)
509             {
510               char cfg_file_path[PATH_MAX_LENGTH];
511               char buffer[PATH_MAX_LENGTH];
512               osd_get_path(FILETYPE_CONFIG, buffer);
513               sprintf(cfg_file_path, "%s%s%s.cfg", buffer, PATH_DEFAULT_SLASH(), options.romset_filename_noext);
514               buffer[0] = '\0';
515 
516               if(path_is_valid(cfg_file_path))
517               {
518                 if(!remove(cfg_file_path) == 0)
519                   sprintf(buffer, "%s.cfg exists but cannot be deleted!\n", options.romset_filename_noext);
520                 else
521                   sprintf(buffer, "%s.cfg exists but cannot be deleted!\n", options.romset_filename_noext);
522               }
523               log_cb(RETRO_LOG_INFO, LOGPRE "%s Reloading input maps.\n", buffer);
524               usrintf_showmessage_secs(4, "%s Reloading input maps.", buffer);
525 
526               load_input_port_settings(); /* this may just read the active mappings from memory (ie the same ones we're trying to delete) rather than resetting them to default */
527               /* should use reset_driver_inputs() if that function is ever completed */
528 
529               old_dual_joystick_state = options.dual_joysticks;
530             }
531             break;
532           }
533           else /* always disabled except when options.content_flags[CONTENT_DUAL_JOYSTICK] has been set to true */
534           {
535             options.dual_joysticks = false;
536             break;
537           }
538 
539         case OPT_RSTICK_BTNS:
540           if(strcmp(var.value, "enabled") == 0)
541             options.rstick_to_btns = 1;
542           else
543             options.rstick_to_btns = 0;
544           break;
545 
546         case OPT_TATE_MODE:
547           if(strcmp(var.value, "enabled") == 0)
548             options.tate_mode = 1;
549           else
550             options.tate_mode = 0;
551           break;
552 
553         case OPT_VECTOR_RESOLUTION:
554           if(strcmp(var.value, "640x480") == 0)
555           {
556             options.vector_width=640;
557             options.vector_height=480;
558           }
559           else if(strcmp(var.value, "1024x768") == 0)
560           {
561             options.vector_width=1024;
562             options.vector_height=768;
563           }
564           else if(strcmp(var.value, "1280x960") == 0)
565           {
566             options.vector_width=1280;
567             options.vector_height=960;
568           }
569           else if(strcmp(var.value, "1440x1080") == 0)
570           {
571             options.vector_width=1440;
572             options.vector_height=1080;
573           }
574           else if(strcmp(var.value, "1600x1200") == 0)
575           {
576             options.vector_width=1600;
577             options.vector_height=1200;
578           }
579           else
580           {
581             options.vector_width=0; // mame will set this from the driver resolution set
582             options.vector_height=0;
583           }
584           break;
585 
586         case OPT_VECTOR_ANTIALIAS:
587           if(strcmp(var.value, "enabled") == 0)
588             options.antialias = 1; /* integer: 1 to enable antialiasing on vectors _ does not work as of 2018/04/17*/
589           else
590             options.antialias = 0;
591           break;
592 
593           case OPT_VECTOR_BEAM:
594           options.beam = atof(var.value); /* float: vector beam width */
595           break;
596 
597         case OPT_VECTOR_TRANSLUCENCY:
598           if(strcmp(var.value, "enabled") == 0)
599             options.translucency = 1; /* integer: 1 to enable translucency on vectors */
600           else
601             options.translucency = 0;
602           break;
603 
604         case OPT_VECTOR_FLICKER:
605           options.vector_flicker = atof(var.value);
606           break;
607 
608         case OPT_VECTOR_INTENSITY:
609           options.vector_intensity_correction = atof(var.value); /* float: vector beam intensity */
610           break;
611 
612         case OPT_NVRAM_BOOTSTRAP:
613           if(strcmp(var.value, "enabled") == 0)
614             options.nvram_bootstrap = true;
615           else
616             options.nvram_bootstrap = false;
617           break;
618 
619         case OPT_SAMPLE_RATE:
620           options.samplerate = atoi(var.value);
621           break;
622 
623         case OPT_DCS_SPEEDHACK:
624           if(strcmp(var.value, "enabled") == 0)
625             options.activate_dcs_speedhack = 1;
626           else
627             options.activate_dcs_speedhack = 0;
628           break;
629 
630         case OPT_MAME_REMAPPING:
631           if(strcmp(var.value, "enabled") == 0)
632             options.mame_remapping = true;
633           else
634             options.mame_remapping = false;
635           if(!first_time)
636             setup_menu_init();
637           break;
638 
639         case OPT_FRAMESKIP:
640           options.frameskip = atoi(var.value);
641           break;
642 
643         case OPT_CORE_SYS_SUBFOLDER:
644           if(strcmp(var.value, "enabled") == 0)
645             options.system_subfolder = true;
646           else
647             options.system_subfolder = false;
648           break;
649 
650           case OPT_CORE_SAVE_SUBFOLDER:
651           if(strcmp(var.value, "enabled") == 0)
652             options.save_subfolder = true;
653           else
654             options.save_subfolder = false;
655           break;
656 
657 	    case OPT_Cheat_Input_Ports:
658           if(strcmp(var.value, "enabled") == 0)
659             options.cheat_input_ports = true;
660           else
661             options.cheat_input_ports = false;
662           break;
663 	    case OPT_Machine_Timing:
664           if(strcmp(var.value, "enabled") == 0)
665             options.machine_timing = true;
666           else
667             options.machine_timing = false;
668           break;
669 	  }
670     }
671   }
672 
673   /*if(!options.content_flags[CONTENT_ALT_SOUND])*/
674     options.use_samples = true;
675 
676   ledintf.set_led_state = NULL;
677   environ_cb(RETRO_ENVIRONMENT_GET_LED_INTERFACE, &ledintf);
678   led_state_cb = ledintf.set_led_state;
679 
680   if(reset_control_descriptions) /* one of the option changes has flagged a need to re-describe the controls */
681   {
682     /*retro_describe_controls();*/
683     reset_control_descriptions = false;
684   }
685 }
686 
687 
retro_get_system_av_info(struct retro_system_av_info * info)688 void retro_get_system_av_info(struct retro_system_av_info *info)
689 {
690   mame2003_video_get_geometry(&info->geometry);
691   if(options.machine_timing)
692   {
693     if (Machine->drv->frames_per_second < 60.0 )
694       info->timing.fps = 60.0;
695     else
696       info->timing.fps = Machine->drv->frames_per_second; /* qbert is 61 fps */
697 
698     if ( (Machine->drv->frames_per_second * 1000 < options.samplerate) || ( Machine->drv->frames_per_second < 60) )
699     {
700       info->timing.sample_rate = Machine->drv->frames_per_second * 1000;
701       log_cb(RETRO_LOG_INFO, LOGPRE "Sample timing rate too high for framerate required dropping to %f\n",  Machine->drv->frames_per_second * 1000);
702     }
703 
704     else
705     {
706       info->timing.sample_rate = options.samplerate;
707       log_cb(RETRO_LOG_INFO, LOGPRE "Sample rate set to %d\n",options.samplerate);
708     }
709   }
710 
711   else
712   {
713     info->timing.fps = Machine->drv->frames_per_second;
714 
715     if ( Machine->drv->frames_per_second * 1000 < options.samplerate)
716      info->timing.sample_rate = 22050;
717 
718     else
719      info->timing.sample_rate = options.samplerate;
720   }
721 
722 }
723 
724 
retro_api_version(void)725 unsigned retro_api_version(void)
726 {
727   return RETRO_API_VERSION;
728 }
729 
retro_get_system_info(struct retro_system_info * info)730 void retro_get_system_info(struct retro_system_info *info)
731 {
732    /* this must match the 'corename' field in mame2003_libretro.info
733     * in order for netplay to work. */
734    info->library_name = "MAME 2003 (0.78)";
735 #ifndef GIT_VERSION
736 #define GIT_VERSION ""
737 #endif
738    info->library_version = "0.78" GIT_VERSION;
739    info->valid_extensions = "zip";
740    info->need_fullpath = true;
741    info->block_extract = true;
742 }
743 
744 #define describe_buttons(INDEX) \
745   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT,   "Joystick Left" },\
746   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT,  "Joystick Right" },\
747   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP,     "Joystick Up" },\
748   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN,   "Joystick Down" },\
749   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B,      "Button 1" },\
750   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y,      "Button 2" },\
751   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X,      "Button 3" },\
752   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A,      "Button 4" },\
753   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L,      "Button 5" },\
754   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R,      "Button 6" },\
755   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2,     "Button 7" },\
756   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2,     "Button 8" },\
757   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3,     "Button 9" },\
758   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3,     "Button 10" },\
759   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Insert Coin" },\
760   { INDEX, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START,  "Start" },
761 
762 struct retro_input_descriptor desc[] = {
763   describe_buttons(0)
764   describe_buttons(1)
765   describe_buttons(2)
766   describe_buttons(3)
767   { 0, 0, 0, 0, NULL }
768 };
769 
remove_slash(char * temp)770 static void remove_slash (char* temp)
771 {
772   int i;
773 
774   for(i=0; temp[i] != '\0'; ++i);
775 
776   log_cb(RETRO_LOG_INFO, LOGPRE "Check for trailing slash in path: %s\n", temp);
777 
778   if( (temp[i-1] == '/' || temp[i-1] == '\\') && (i > 1) )
779   {
780     temp[i-1] = 0;
781     log_cb(RETRO_LOG_INFO, LOGPRE "Removed a trailing slash in path: %s\n", temp);
782   }
783   else
784     log_cb(RETRO_LOG_INFO, LOGPRE "Trailing slash removal was not necessary for path given.\n");
785 }
786 
retro_load_game(const struct retro_game_info * game)787 bool retro_load_game(const struct retro_game_info *game)
788 {
789   int i;
790   int              driverIndex    = 0;
791   int              port_index;
792   char             *driver_lookup = NULL;
793 
794   if(string_is_empty(game->path))
795   {
796     log_cb(RETRO_LOG_ERROR, LOGPRE "Content path is not set. Exiting!\n");
797     return false;
798   }
799 
800   log_cb(RETRO_LOG_INFO, LOGPRE "Full content path %s\n", game->path);
801   if(!path_is_valid(game->path))
802   {
803     log_cb(RETRO_LOG_ERROR, LOGPRE "Content path is not valid. Exiting!");
804     return false;
805   }
806   log_cb(RETRO_LOG_INFO, LOGPRE "Git Version %s\n",GIT_VERSION);
807   driver_lookup = auto_strdup(path_basename(game->path));
808   path_remove_extension(driver_lookup);
809 
810   log_cb(RETRO_LOG_INFO, LOGPRE "Content lookup name: %s\n", driver_lookup);
811 
812   for (driverIndex = 0; driverIndex < total_drivers; driverIndex++)
813   {
814     const struct GameDriver *needle = drivers[driverIndex];
815 
816     if ( strcasecmp(driver_lookup, needle->name) == 0 )
817     {
818       log_cb(RETRO_LOG_INFO, LOGPRE "Driver index counter: %d. Matched game driver: %s\n",  driverIndex, needle->name);
819       game_driver = needle;
820       options.romset_filename_noext = driver_lookup;
821       break;
822     }
823 	if(driverIndex == total_drivers -2) // we could fix the total drives in drivers c but the it pointless its taken into account here
824 	{
825       log_cb(RETRO_LOG_ERROR, LOGPRE "Driver index counter: %d. Game driver not found for %s!\n", driverIndex, driver_lookup);
826       return false;
827 	}
828  }
829 
830    if(!init_game(driverIndex))
831     return false;
832 
833   #if (HAS_CYCLONE || HAS_DRZ80)
834    int use_cyclone = 1;
835    int use_drz80 = 1;
836    int use_drz80_snd = 1;
837 
838 	for (i=0;i<NUMGAMES;i++)
839  	{
840 		if (strcmp(drivers[driverIndex]->name,fe_drivers[i].name)==0)
841 		{
842 			/* ASM cores: 0=None,1=Cyclone,2=DrZ80,3=Cyclone+DrZ80,4=DrZ80(snd),5=Cyclone+DrZ80(snd) */
843          switch (fe_drivers[i].cores)
844          {
845          case 0:
846             use_cyclone = 0;
847 				use_drz80_snd = 0;
848 				use_drz80 = 0;
849             break;
850          case 1:
851 				use_drz80_snd = 0;
852 				use_drz80 = 0;
853             break;
854          case 2:
855             use_cyclone = 0;
856             break;
857          case 4:
858             use_cyclone = 0;
859 				use_drz80 = 0;
860             break;
861          case 5:
862 				use_drz80 = 0;
863             break;
864          default:
865             break;
866          }
867 
868          break;
869 		}
870 	}
871 
872    /* Replace M68000 by CYCLONE */
873 #if (HAS_CYCLONE)
874    if (use_cyclone)
875    {
876 	   for (i=0;i<MAX_CPU;i++)
877 	   {
878 		   unsigned int *type=(unsigned int *)&(Machine->drv->cpu[i].cpu_type);
879 #ifdef NEOMAME
880 		   if (*type==CPU_M68000)
881 #else
882 			   if (*type==CPU_M68000 || *type==CPU_M68010 )
883 #endif
884 			   {
885 				   *type=CPU_CYCLONE;
886                    log_cb(RETRO_LOG_INFO, LOGPRE "Replaced CPU_CYCLONE\n");
887 			   }
888         if(!(*type)){
889           break;
890         }
891 	   }
892    }
893 #endif
894 
895 #if (HAS_DRZ80)
896 	/* Replace Z80 by DRZ80 */
897 	if (use_drz80)
898 	{
899 		for (i=0;i<MAX_CPU;i++)
900 		{
901 			unsigned int *type=(unsigned int *)&(Machine->drv->cpu[i].cpu_type);
902 			if (type==CPU_Z80)
903 			{
904 				*type=CPU_DRZ80;
905         log_cb(RETRO_LOG_INFO, LOGPRE "Replaced Z80\n");
906 			}
907 		}
908 	}
909 
910 	/* Replace Z80 with DRZ80 only for sound CPUs */
911 	if (use_drz80_snd)
912 	{
913 		for (i=0;i<MAX_CPU;i++)
914 		{
915 			int *type=(int*)&(Machine->drv->cpu[i].cpu_type);
916 			if (type==CPU_Z80 && Machine->drv->cpu[i].cpu_flags&CPU_AUDIO_CPU)
917 			{
918 				*type=CPU_DRZ80;
919         log_cb(RETRO_LOG_INFO, LOGPRE "Replaced Z80 sound\n");
920 
921 			}
922 		}
923 	}
924 #endif
925 
926 #endif
927 
928   set_content_flags();
929 
930   options.libretro_content_path = auto_strdup(game->path);
931   path_basedir(options.libretro_content_path);
932 
933   /* Get system directory from frontend */
934   options.libretro_system_path = NULL;
935   environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY,&options.libretro_system_path);
936   if (options.libretro_system_path == NULL || options.libretro_system_path[0] == '\0')
937   {
938       log_cb(RETRO_LOG_INFO, LOGPRE "libretro system path not set by frontend, using content path\n");
939       options.libretro_system_path = options.libretro_content_path;
940   }
941 
942   /* Get save directory from frontend */
943   options.libretro_save_path = NULL;
944   environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY,&options.libretro_save_path);
945   if (options.libretro_save_path == NULL || options.libretro_save_path[0] == '\0')
946   {
947       log_cb(RETRO_LOG_INFO,  LOGPRE "libretro save path not set by frontend, using content path\n");
948       options.libretro_save_path = options.libretro_content_path;
949   }
950 
951   /* Remove trailing slashes for specified systems */
952   remove_slash(options.libretro_content_path);
953   remove_slash(options.libretro_system_path);
954   remove_slash(options.libretro_save_path);
955 
956   log_cb(RETRO_LOG_INFO, LOGPRE "content path: %s\n", options.libretro_content_path);
957   log_cb(RETRO_LOG_INFO, LOGPRE " system path: %s\n", options.libretro_system_path);
958   log_cb(RETRO_LOG_INFO, LOGPRE "   save path: %s\n", options.libretro_save_path);
959 
960 
961   init_core_options();
962   update_variables(true);
963 
964   environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
965 
966   if(!run_game(driverIndex))
967     return true;
968 
969   return false;
970 }
971 
set_content_flags(void)972 static void set_content_flags(void)
973 {
974   int i = 0;
975 
976   extern struct GameDriver driver_neogeo;
977   extern struct GameDriver driver_stvbios;
978   const struct InputPortTiny *input = game_driver->input_ports;
979 
980 
981   /************ DRIVERS WITH ALTERNATE SOUNDTRACKS ************/
982   for( i = 0; Machine->drv->sound[i].sound_type && i < MAX_SOUND; i++ )
983   {
984     if (Machine->drv->sound[i].tag)
985       if (strcmp("OST Samples",  Machine->drv->sound[i].tag) == 0)
986       {
987         options.content_flags[CONTENT_ALT_SOUND] = true;
988         log_cb(RETRO_LOG_INFO, LOGPRE "Content has an alternative audio option controlled via core option.\n");
989       }
990   }
991 
992   /************ DRIVERS WITH MULTIPLE BIOS OPTIONS ************/
993   if (game_driver->clone_of == &driver_neogeo
994    ||(game_driver->clone_of && game_driver->clone_of->clone_of == &driver_neogeo))
995   {
996     options.content_flags[CONTENT_NEOGEO] = true;
997     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as a Neo Geo game.\n");
998   }
999   else if (game_driver->clone_of == &driver_stvbios
1000    ||(game_driver->clone_of && game_driver->clone_of->clone_of == &driver_stvbios))
1001   {
1002     options.content_flags[CONTENT_STV] = true;
1003     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as a ST-V game.\n");
1004   }
1005 
1006   /************ DIE HARD: ARCADE ************/
1007   if(strcasecmp(game_driver->name, "diehard") == 0)
1008   {
1009     options.content_flags[CONTENT_DIEHARD] = true;
1010     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as \"Die Hard: Arcade\". BIOS will be set to \"us\".\n");
1011   }
1012 
1013   /************ DRIVERS WITH VECTOR VIDEO DISPLAYS ************/
1014   if(Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
1015   {
1016     options.content_flags[CONTENT_VECTOR] = true;
1017     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as using a vector video display.\n");
1018   }
1019 
1020   /************ INPUT-BASED CONTENT FLAGS ************/
1021 
1022   options.content_flags[CONTENT_JOYSTICK_DIRECTIONS] = 8; /* default behavior is 8-way joystick, even for 2-way games */
1023 
1024 	while ((input->type & ~IPF_MASK) != IPT_END)
1025 	{
1026 		/* skip analog extension fields */
1027 		if ((input->type & ~IPF_MASK) != IPT_EXTENSION)
1028 		{
1029 			switch (input->type & IPF_PLAYERMASK)
1030 			{
1031 				case IPF_PLAYER1:
1032 					if (options.content_flags[CONTENT_PLAYER_COUNT] < 1) options.content_flags[CONTENT_PLAYER_COUNT] = 1;
1033 					break;
1034 				case IPF_PLAYER2:
1035 					if (options.content_flags[CONTENT_PLAYER_COUNT] < 2) options.content_flags[CONTENT_PLAYER_COUNT] = 2;
1036 					break;
1037 				case IPF_PLAYER3:
1038 					if (options.content_flags[CONTENT_PLAYER_COUNT] < 3) options.content_flags[CONTENT_PLAYER_COUNT] = 3;
1039 					break;
1040 				case IPF_PLAYER4:
1041 					if (options.content_flags[CONTENT_PLAYER_COUNT] < 4) options.content_flags[CONTENT_PLAYER_COUNT] = 4;
1042 					break;
1043 				case IPF_PLAYER5:
1044 					if (options.content_flags[CONTENT_PLAYER_COUNT] < 5) options.content_flags[CONTENT_PLAYER_COUNT] = 5;
1045 					break;
1046 				case IPF_PLAYER6:
1047 					if (options.content_flags[CONTENT_PLAYER_COUNT] < 6) options.content_flags[CONTENT_PLAYER_COUNT] = 6;
1048 					break;
1049 			}
1050 
1051       if (input->type & IPF_4WAY) /* original controls used a 4-way joystick */
1052       {
1053         options.content_flags[CONTENT_JOYSTICK_DIRECTIONS] = 4;
1054       }
1055 
1056 			switch (input->type & ~IPF_MASK)
1057 			{
1058 				case IPT_JOYSTICKRIGHT_UP:
1059 				case IPT_JOYSTICKRIGHT_DOWN:
1060 				case IPT_JOYSTICKRIGHT_LEFT:
1061 				case IPT_JOYSTICKRIGHT_RIGHT:
1062 				case IPT_JOYSTICKLEFT_UP:
1063 				case IPT_JOYSTICKLEFT_DOWN:
1064 				case IPT_JOYSTICKLEFT_LEFT:
1065 				case IPT_JOYSTICKLEFT_RIGHT:
1066                     options.content_flags[CONTENT_DUAL_JOYSTICK] = true; /* if there are any "JOYSTICKLEFT" mappings we know there are two joysticks */
1067 					break;
1068 				case IPT_BUTTON1:
1069 					if (options.content_flags[CONTENT_BUTTON_COUNT] < 1) options.content_flags[CONTENT_BUTTON_COUNT] = 1;
1070 					break;
1071 				case IPT_BUTTON2:
1072 					if (options.content_flags[CONTENT_BUTTON_COUNT] < 2) options.content_flags[CONTENT_BUTTON_COUNT] = 2;
1073 					break;
1074 				case IPT_BUTTON3:
1075 					if (options.content_flags[CONTENT_BUTTON_COUNT] < 3) options.content_flags[CONTENT_BUTTON_COUNT] = 3;
1076 					break;
1077 				case IPT_BUTTON4:
1078 					if (options.content_flags[CONTENT_BUTTON_COUNT] < 4) options.content_flags[CONTENT_BUTTON_COUNT] = 4;
1079 					break;
1080 				case IPT_BUTTON5:
1081 					if (options.content_flags[CONTENT_BUTTON_COUNT] < 5) options.content_flags[CONTENT_BUTTON_COUNT] = 5;
1082 					break;
1083 				case IPT_BUTTON6:
1084 					if (options.content_flags[CONTENT_BUTTON_COUNT] <6 ) options.content_flags[CONTENT_BUTTON_COUNT] = 6;
1085 					break;
1086 				case IPT_BUTTON7:
1087 					if (options.content_flags[CONTENT_BUTTON_COUNT] < 7) options.content_flags[CONTENT_BUTTON_COUNT] = 7;
1088 					break;
1089 				case IPT_BUTTON8:
1090 					if (options.content_flags[CONTENT_BUTTON_COUNT] < 8) options.content_flags[CONTENT_BUTTON_COUNT] = 8;
1091 					break;
1092 				case IPT_BUTTON9:
1093 					if (options.content_flags[CONTENT_BUTTON_COUNT] < 9) options.content_flags[CONTENT_BUTTON_COUNT] = 9;
1094 					break;
1095 				case IPT_BUTTON10:
1096 					if (options.content_flags[CONTENT_BUTTON_COUNT] < 10) options.content_flags[CONTENT_BUTTON_COUNT] = 10;
1097 					break;
1098 				case IPT_PADDLE:
1099           options.content_flags[CONTENT_PADDLE] = true;
1100           log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as using paddle controls.\n");
1101           break;
1102 				case IPT_DIAL:
1103           options.content_flags[CONTENT_DIAL] = true;
1104           log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as using dial controls.\n");
1105 					break;
1106 				case IPT_TRACKBALL_X:
1107 				case IPT_TRACKBALL_Y:
1108           options.content_flags[CONTENT_TRACKBALL] = true;
1109           log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as using trackball controls.\n");
1110 					break;
1111 				case IPT_AD_STICK_X:
1112 				case IPT_AD_STICK_Y:
1113           options.content_flags[CONTENT_AD_STICK] = true;
1114           log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as using Analog/Digital stick controls.\n");
1115 					break;
1116 				case IPT_LIGHTGUN_X:
1117 				case IPT_LIGHTGUN_Y:
1118           options.content_flags[CONTENT_LIGHTGUN] = true;
1119           log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as using Analog/Digital stick controls.\n");
1120 					break;
1121 				case IPT_SERVICE :
1122           options.content_flags[CONTENT_HAS_SERVICE] = true;
1123           log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as having a service button.\n");
1124 					break;
1125 				case IPT_TILT :
1126           options.content_flags[CONTENT_HAS_TILT] = true;
1127           log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as having a tilt feature.\n");
1128 					break;
1129 			}
1130 		}
1131 		++input;
1132 	}
1133 
1134   if(options.content_flags[CONTENT_DUAL_JOYSTICK] == true)
1135     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as using \"dual joystick\" controls.\n");
1136 
1137   if (options.content_flags[CONTENT_JOYSTICK_DIRECTIONS] == 4)
1138     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as using 4-way joystick controls.\n");
1139   else
1140     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as using 8-way joystick controls.\n");
1141 
1142   /************ DRIVERS FLAGGED IN CONTROLS.C WITH 45-DEGREE JOYSTICK ROTATION ************/
1143   if(game_driver->ctrl_dat->rotate_joy_45)
1144   {
1145     options.content_flags[CONTENT_ROTATE_JOY_45] = true;
1146     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified by controls.c as joysticks rotated 45-degrees with respect to the cabinet.\n");
1147   }
1148   else
1149     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified by controls.c as having joysticks on axis with respect to the cabinet.\n");
1150 
1151   /************ DRIVERS FLAGGED IN CONTROLS.C WITH ALTERNATING CONTROLS ************/
1152   if(game_driver->ctrl_dat->alternating_controls)
1153   {
1154     options.content_flags[CONTENT_ALTERNATING_CTRLS] = true;
1155     /* there may or may not be some need to have a ctrl_count different than player_count, perhaps because of some
1156        alternating controls layout. this is a place to check some condition and make the two numbers different
1157        if that should ever prove useful. */
1158     if(true)
1159       options.content_flags[CONTENT_CTRL_COUNT] = options.content_flags[CONTENT_PLAYER_COUNT];
1160   }
1161   else
1162     options.content_flags[CONTENT_CTRL_COUNT] = options.content_flags[CONTENT_PLAYER_COUNT];
1163 
1164   log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as supporting %i players with %i distinct controls.\n", options.content_flags[CONTENT_PLAYER_COUNT], options.content_flags[CONTENT_CTRL_COUNT]);
1165   log_cb(RETRO_LOG_INFO, LOGPRE "Content identified as supporting %i button controls.\n", options.content_flags[CONTENT_BUTTON_COUNT]);
1166 
1167 
1168   /************ DRIVERS FLAGGED IN CONTROLS.C WITH MIRRORED CONTROLS ************/
1169   if(game_driver->ctrl_dat->mirrored_controls)
1170   {
1171     options.content_flags[CONTENT_MIRRORED_CTRLS] = true;
1172     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified by controls.c as having mirrored multiplayer control labels.\n");
1173   }
1174   else
1175     log_cb(RETRO_LOG_INFO, LOGPRE "Content identified by controls.c as having non-mirrored multiplayer control labels.\n");
1176 
1177 
1178   /************ DCS DRIVERS WITH SPEEDDUP HACKS ************/
1179   while(/*dcs_drivers[i]*/true)
1180   {
1181     if(/*strcmp(dcs_drivers[i], game_driver->name) == 0*/true)
1182     {
1183       options.content_flags[CONTENT_DCS_SPEEDHACK] = true;
1184       /*log_cb(RETRO_LOG_INFO, LOGPRE "DCS content has a speedup hack controlled via core option.\n");*/
1185       break;
1186     }
1187     i++;
1188   }
1189 
1190   /************ DRIVERS WITH NVRAM BOOTSTRAP PATCHES ************/
1191   if(game_driver->bootstrap != NULL)
1192   {
1193     options.content_flags[CONTENT_NVRAM_BOOTSTRAP] = true;
1194     log_cb(RETRO_LOG_INFO, LOGPRE "Content has an NVRAM bootstrap controlled via core option.\n");
1195   }
1196 
1197 }
1198 
retro_reset(void)1199 void retro_reset (void)
1200 {
1201     machine_reset(); /* use internal core function */
1202 }
1203 
1204 /* get pointer axis vector from coord */
get_pointer_delta(int16_t coord,int16_t * prev_coord)1205 int16_t get_pointer_delta(int16_t coord, int16_t *prev_coord)
1206 {
1207    int16_t delta = 0;
1208    if (*prev_coord == 0 || coord == 0)
1209    {
1210       *prev_coord = coord;
1211    }
1212    else
1213    {
1214       if (coord != *prev_coord)
1215       {
1216          delta = coord - *prev_coord;
1217          *prev_coord = coord;
1218       }
1219    }
1220 
1221    return delta;
1222 }
1223 
retro_run(void)1224 void retro_run (void)
1225 {
1226 	int i;
1227 	bool pointer_pressed;
1228 	const struct KeyboardInfo *thisInput;
1229 	bool updated = false;
1230 
1231 	poll_cb();
1232 
1233 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
1234 		update_variables(false);
1235 
1236 	/* Keyboard */
1237 	thisInput = retroKeys;
1238 	while(thisInput->name)
1239 	{
1240 		retroKeyState[thisInput->code] = input_cb(0, RETRO_DEVICE_KEYBOARD, 0, thisInput->code);
1241 		thisInput ++;
1242 	}
1243 
1244 	for (i = 0; i < 4; i ++)
1245 	{
1246       unsigned int offset = (i * 18);
1247 
1248       /* Analog joystick */
1249       analogjoy[i][0] = input_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X);
1250       analogjoy[i][1] = input_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y);
1251       analogjoy[i][2] = input_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X);
1252       analogjoy[i][3] = input_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y);
1253 
1254       /* Joystick */
1255       if (options.rstick_to_btns)
1256       {
1257          /* if less than 0.5 force, ignore and read buttons as usual */
1258          retroJsState[0 + offset] = analogjoy[i][3] >  0x4000 ? 1 : input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B);
1259          retroJsState[1 + offset] = analogjoy[i][2] < -0x4000 ? 1 : input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y);
1260       }
1261       else
1262       {
1263          retroJsState[0 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B);
1264          retroJsState[1 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y);
1265       }
1266       retroJsState[2 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT);
1267       retroJsState[3 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START);
1268       retroJsState[4 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP);
1269       retroJsState[5 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN);
1270       retroJsState[6 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT);
1271       retroJsState[7 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT);
1272       if (options.rstick_to_btns)
1273       {
1274          retroJsState[8 + offset] = analogjoy[i][2] >  0x4000 ? 1 : input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A);
1275          retroJsState[9 + offset] = analogjoy[i][3] < -0x4000 ? 1 : input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X);
1276       }
1277       else
1278       {
1279          retroJsState[8 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A);
1280          retroJsState[9 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X);
1281       }
1282       retroJsState[10 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L);
1283       retroJsState[11 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R);
1284       retroJsState[12 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2);
1285       retroJsState[13 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2);
1286       retroJsState[14 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3);
1287       retroJsState[15 + offset] = input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3);
1288 
1289       if (options.mouse_device)
1290       {
1291          if (options.mouse_device == RETRO_DEVICE_MOUSE)
1292          {
1293             retroJsState[16 + offset] = input_cb(i, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT);
1294             retroJsState[17 + offset] = input_cb(i, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT);
1295             mouse_x[i] = input_cb(i, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
1296             mouse_y[i] = input_cb(i, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
1297          }
1298          else /* RETRO_DEVICE_POINTER */
1299          {
1300             pointer_pressed = input_cb(i, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED);
1301             retroJsState[16 + offset] = pointer_pressed;
1302             retroJsState[17 + offset] = 0; /* padding */
1303             mouse_x[i] = pointer_pressed ? get_pointer_delta(input_cb(i, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X), &prev_pointer_x) : 0;
1304             mouse_y[i] = pointer_pressed ? get_pointer_delta(input_cb(i, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y), &prev_pointer_y) : 0;
1305          }
1306       }
1307       else
1308       {
1309          retroJsState[16 + offset] = 0;
1310          retroJsState[17 + offset] = 0;
1311       }
1312 
1313       if ( (options.rstick_to_btns) && (options.content_flags[CONTENT_DUAL_JOYSTICK]) )
1314       {
1315          retroJsState[21 + offset] = analogjoy[i][2] >  0x4000 ? 1 : input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A);
1316          retroJsState[20 + offset] = analogjoy[i][3] < -0x4000 ? 1 : input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X);
1317          retroJsState[18 + offset] = analogjoy[i][3] >  0x4000 ? 1 : input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B);
1318          retroJsState[19 + offset] = analogjoy[i][2] < -0x4000 ? 1 : input_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y);
1319 	    }
1320       else
1321 	    {
1322         retroJsState[21 + offset] = analogjoy[i][2] >  0x4000 ? 1 : 0;
1323         retroJsState[19 + offset] = analogjoy[i][2] < -0x4000 ? 1 : 0;
1324         retroJsState[18 + offset] = analogjoy[i][3] >  0x4000 ? 1 : 0;
1325         retroJsState[20 + offset] = analogjoy[i][3] < -0x4000 ? 1 : 0;
1326 	    }
1327   }
1328 
1329    mame_frame();
1330 }
1331 
retro_unload_game(void)1332 void retro_unload_game(void)
1333 {
1334     mame_done();
1335     /* do we need to be freeing things here? */
1336 
1337     free(options.romset_filename_noext);
1338 }
1339 
retro_deinit(void)1340 void retro_deinit(void)
1341 {
1342 #ifdef LOG_PERFORMANCE
1343    perf_cb.perf_log();
1344 #endif
1345 }
1346 
1347 extern size_t state_get_dump_size(void);
1348 
retro_serialize_size(void)1349 size_t retro_serialize_size(void)
1350 {
1351     return state_get_dump_size();
1352 }
1353 
retro_serialize(void * data,size_t size)1354 bool retro_serialize(void *data, size_t size)
1355 {
1356    int cpunum;
1357 	if(  retro_serialize_size() == size  && size   )
1358 	{
1359 		/* write the save state */
1360 		state_save_save_begin(data);
1361 
1362 		/* write tag 0 */
1363 		state_save_set_current_tag(0);
1364 		if(state_save_save_continue())
1365 		{
1366 		    return false;
1367 		}
1368 
1369 		/* loop over CPUs */
1370 		for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
1371 		{
1372 			cpuintrf_push_context(cpunum);
1373 
1374 			/* make sure banking is set */
1375 			activecpu_reset_banking();
1376 
1377 			/* save the CPU data */
1378 			state_save_set_current_tag(cpunum + 1);
1379 			if(state_save_save_continue())
1380 			    return false;
1381 
1382 			cpuintrf_pop_context();
1383 		}
1384 
1385 		/* finish and close */
1386 		state_save_save_finish();
1387 
1388 		return true;
1389 	}
1390 
1391 	return false;
1392 }
1393 
retro_unserialize(const void * data,size_t size)1394 bool retro_unserialize(const void * data, size_t size)
1395 {
1396     int cpunum;
1397 	/* if successful, load it */
1398 	if ( (retro_serialize_size() ) && ( data ) && ( size ) && ( !state_save_load_begin((void*)data, size) ) )
1399 	{
1400         /* read tag 0 */
1401         state_save_set_current_tag(0);
1402         if(state_save_load_continue())
1403             return false;
1404 
1405         /* loop over CPUs */
1406         for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
1407         {
1408             cpuintrf_push_context(cpunum);
1409 
1410             /* make sure banking is set */
1411             activecpu_reset_banking();
1412 
1413             /* load the CPU data */
1414             state_save_set_current_tag(cpunum + 1);
1415             if(state_save_load_continue())
1416                 return false;
1417 
1418             cpuintrf_pop_context();
1419         }
1420 
1421         /* finish and close */
1422         state_save_load_finish();
1423 
1424 
1425         return true;
1426 	}
1427 
1428 	return false;
1429 }
1430 
1431 /******************************************************************************
1432 
1433   Sound
1434 
1435   osd_start_audio_stream() is called at the start of the emulation to initialize
1436   the output stream, then osd_update_audio_stream() is called every frame to
1437   feed new data. osd_stop_audio_stream() is called when the emulation is stopped.
1438 
1439   The sample rate is fixed at Machine->sample_rate. Samples are 16-bit, signed.
1440   When the stream is stereo, left and right samples are alternated in the
1441   stream.
1442 
1443   osd_start_audio_stream() and osd_update_audio_stream() must return the number
1444   of samples (or couples of samples, when using stereo) required for next frame.
1445   This will be around Machine->sample_rate / Machine->drv->frames_per_second,
1446   the code may adjust it by SMALL AMOUNTS to keep timing accurate and to
1447   maintain audio and video in sync when using vsync. Note that sound emulation,
1448   especially when DACs are involved, greatly depends on the number of samples
1449   per frame to be roughly constant, so the returned value must always stay close
1450   to the reference value of Machine->sample_rate / Machine->drv->frames_per_second.
1451   Of course that value is not necessarily an integer so at least a +/- 1
1452   adjustment is necessary to avoid drifting over time.
1453 
1454 ******************************************************************************/
1455 
osd_start_audio_stream(int stereo)1456 int osd_start_audio_stream(int stereo)
1457 {
1458   if (options.machine_timing)
1459   {
1460     if ( ( Machine->drv->frames_per_second * 1000 < options.samplerate) || (Machine->drv->frames_per_second < 60) )
1461       Machine->sample_rate = Machine->drv->frames_per_second * 1000;
1462 
1463     else Machine->sample_rate = options.samplerate;
1464   }
1465 
1466   else
1467   {
1468     if ( Machine->drv->frames_per_second * 1000 < options.samplerate)
1469       Machine->sample_rate=22050;
1470 
1471     else
1472       Machine->sample_rate = options.samplerate;
1473   }
1474 
1475   delta_samples = 0.0f;
1476   usestereo = stereo ? 1 : 0;
1477 
1478   /* determine the number of samples per frame */
1479   samples_per_frame = Machine->sample_rate / Machine->drv->frames_per_second;
1480   orig_samples_per_frame = samples_per_frame;
1481 
1482   if (Machine->sample_rate == 0) return 0;
1483 
1484   samples_buffer = (short *) calloc(samples_per_frame+16, 2 + usestereo * 2);
1485   if (!usestereo) conversion_buffer = (short *) calloc(samples_per_frame+16, 4);
1486 
1487   return samples_per_frame;
1488 }
1489 
1490 
osd_update_audio_stream(INT16 * buffer)1491 int osd_update_audio_stream(INT16 *buffer)
1492 {
1493 	int i,j;
1494 	if ( Machine->sample_rate !=0 && buffer )
1495 	{
1496    		memcpy(samples_buffer, buffer, samples_per_frame * (usestereo ? 4 : 2));
1497 		if (usestereo)
1498 			audio_batch_cb(samples_buffer, samples_per_frame);
1499 		else
1500 		{
1501 			for (i = 0, j = 0; i < samples_per_frame; i++)
1502         		{
1503 				conversion_buffer[j++] = samples_buffer[i];
1504 				conversion_buffer[j++] = samples_buffer[i];
1505 		        }
1506          		audio_batch_cb(conversion_buffer,samples_per_frame);
1507 		}
1508 
1509 
1510 		//process next frame
1511 
1512 		if ( samples_per_frame  != orig_samples_per_frame ) samples_per_frame = orig_samples_per_frame;
1513 
1514 		// dont drop any sample frames some games like mk will drift with time
1515 
1516 		delta_samples += (Machine->sample_rate / Machine->drv->frames_per_second) - orig_samples_per_frame;
1517 		if ( delta_samples >= 1.0f )
1518 		{
1519 
1520 			int integer_delta = (int)delta_samples;
1521 			if (integer_delta <= 16 )
1522                         {
1523 				log_cb(RETRO_LOG_DEBUG,"sound: Delta added value %d added to frame\n",integer_delta);
1524 				samples_per_frame += integer_delta;
1525 			}
1526 			else if(integer_delta >= 16) log_cb(RETRO_LOG_INFO, "sound: Delta not added to samples_per_frame too large integer_delta:%d\n", integer_delta);
1527 			else log_cb(RETRO_LOG_DEBUG,"sound(delta) no contitions met\n");
1528 			delta_samples -= integer_delta;
1529 
1530 		}
1531 	}
1532         return samples_per_frame;
1533 }
1534 
1535 
osd_stop_audio_stream(void)1536 void osd_stop_audio_stream(void)
1537 {
1538 }
1539 
1540 
1541 
1542 /******************************************************************************
1543 
1544 Miscellaneous
1545 
1546 ******************************************************************************/
1547 
retro_get_region(void)1548 unsigned retro_get_region (void) {return RETRO_REGION_NTSC;}
retro_get_memory_data(unsigned type)1549 void *retro_get_memory_data(unsigned type) {return 0;}
retro_get_memory_size(unsigned type)1550 size_t retro_get_memory_size(unsigned type) {return 0;}
retro_load_game_special(unsigned game_type,const struct retro_game_info * info,size_t num_info)1551 bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info){return false;}
retro_cheat_reset(void)1552 void retro_cheat_reset(void){}
retro_cheat_set(unsigned unused,bool unused1,const char * unused2)1553 void retro_cheat_set(unsigned unused, bool unused1, const char* unused2){}
retro_set_video_refresh(retro_video_refresh_t cb)1554 void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; }
retro_set_audio_sample(retro_audio_sample_t cb)1555 void retro_set_audio_sample(retro_audio_sample_t cb) { }
retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)1556 void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; }
retro_set_input_poll(retro_input_poll_t cb)1557 void retro_set_input_poll(retro_input_poll_t cb) { poll_cb = cb; }
retro_set_input_state(retro_input_state_t cb)1558 void retro_set_input_state(retro_input_state_t cb) { input_cb = cb; }
1559 
1560 
1561 /******************************************************************************
1562 
1563 	RetroPad mapping
1564 
1565 ******************************************************************************/
1566 
1567 #define EMIT_RETRO_PAD(INDEX) \
1568     {"RetroPad" #INDEX " Left", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_LEFT, JOYCODE_##INDEX##_LEFT}, \
1569     {"RetroPad" #INDEX " Right", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_RIGHT, JOYCODE_##INDEX##_RIGHT}, \
1570     {"RetroPad" #INDEX " Up", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_UP, JOYCODE_##INDEX##_UP}, \
1571     {"RetroPad" #INDEX " Down", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_DOWN, JOYCODE_##INDEX##_DOWN}, \
1572     {"RetroPad" #INDEX " B", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_B, JOYCODE_##INDEX##_BUTTON1}, \
1573     {"RetroPad" #INDEX " Y", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_Y, JOYCODE_##INDEX##_BUTTON2}, \
1574     {"RetroPad" #INDEX " X", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_X, JOYCODE_##INDEX##_BUTTON3}, \
1575     {"RetroPad" #INDEX " A", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_A, JOYCODE_##INDEX##_BUTTON4}, \
1576     {"RetroPad" #INDEX " L", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_L, JOYCODE_##INDEX##_BUTTON5}, \
1577     {"RetroPad" #INDEX " R", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_R, JOYCODE_##INDEX##_BUTTON6}, \
1578     {"RetroPad" #INDEX " L2", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_L2, JOYCODE_##INDEX##_BUTTON7}, \
1579     {"RetroPad" #INDEX " R2", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_R2, JOYCODE_##INDEX##_BUTTON8}, \
1580     {"RetroPad" #INDEX " L3", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_L3, JOYCODE_##INDEX##_BUTTON9}, \
1581     {"RetroPad" #INDEX " R3", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_R3, JOYCODE_##INDEX##_BUTTON10}, \
1582     {"RetroPad" #INDEX " Start", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_START, JOYCODE_##INDEX##_START}, \
1583     {"RetroPad" #INDEX " Select", ((INDEX - 1) * 18) + RETRO_DEVICE_ID_JOYPAD_SELECT, JOYCODE_##INDEX##_SELECT}, \
1584     {"RetroMouse" #INDEX " Left Click", ((INDEX - 1) * 18) + 16, JOYCODE_MOUSE_##INDEX##_BUTTON1}, \
1585     {"RetroMouse" #INDEX " Right Click", ((INDEX - 1) * 18) + 17, JOYCODE_MOUSE_##INDEX##_BUTTON2}
1586 
1587 struct JoystickInfo jsItems[] =
1588 {
1589     EMIT_RETRO_PAD(1),
1590     EMIT_RETRO_PAD(2),
1591     EMIT_RETRO_PAD(3),
1592     EMIT_RETRO_PAD(4),
1593     {0, 0, 0}
1594 };
1595 
1596 /******************************************************************************
1597 
1598 	Joystick & Mouse/Trackball
1599 
1600 ******************************************************************************/
1601 
1602 int16_t mouse_x[4];
1603 int16_t mouse_y[4];
1604 int16_t analogjoy[4][4];
1605 
retro_set_controller_port_device(unsigned in_port,unsigned device)1606 void retro_set_controller_port_device(unsigned in_port, unsigned device){}
1607 
osd_get_joy_list(void)1608 const struct JoystickInfo *osd_get_joy_list(void)
1609 {
1610     return jsItems;
1611 }
1612 
osd_is_joy_pressed(int joycode)1613 int osd_is_joy_pressed(int joycode)
1614 {
1615   if (options.input_interface == RETRO_DEVICE_KEYBOARD)
1616     return 0;
1617 
1618   return (joycode >= 0) ? retroJsState[joycode] : 0;
1619 }
1620 
osd_is_joystick_axis_code(int joycode)1621 int osd_is_joystick_axis_code(int joycode)
1622 {
1623     return 0;
1624 }
1625 
osd_lightgun_read(int player,int * deltax,int * deltay)1626 void osd_lightgun_read(int player, int *deltax, int *deltay)
1627 {
1628 
1629 }
1630 
osd_trak_read(int player,int * deltax,int * deltay)1631 void osd_trak_read(int player, int *deltax, int *deltay)
1632 {
1633     *deltax = mouse_x[player];
1634     *deltay = mouse_y[player];
1635 }
1636 
1637 #ifdef _MSC_VER
1638 #if _MSC_VER < 1800
round(double number)1639 double round(double number)
1640 {
1641   return (number >= 0) ? (int)(number + 0.5) : (int)(number - 0.5);
1642 }
1643 #endif
1644 #endif
1645 
convert_analog_scale(int input)1646 int convert_analog_scale(int input)
1647 {
1648 	static const int TRIGGER_MAX = 0x8000;
1649 	int neg_test=0;
1650 	float scale;
1651 	int trigger_deadzone;
1652 
1653 	if( options.analog_scale)   trigger_deadzone = (32678 /100) * 20;
1654 	if( !options.analog_scale)  trigger_deadzone = (32678 * options.analog_deadzone) / 100;
1655 
1656 	if (input < 0) { input =abs(input); neg_test=1; }
1657 	scale = ((float)TRIGGER_MAX/(float)(TRIGGER_MAX - trigger_deadzone));
1658 
1659 	if ( input > 0 && input > trigger_deadzone )
1660 	{
1661 		// Re-scale analog range
1662 		float scaled = (input - trigger_deadzone)*scale;
1663     input = (int)round(scaled);
1664 
1665 		if (input > +32767)
1666 		{
1667 			input = +32767;
1668 		}
1669 		input = input / 326.78;
1670 	}
1671 
1672 	else
1673 	{
1674 		input = 0;
1675 	}
1676 
1677 
1678 	if (neg_test) input =-abs(input);
1679 	return input * 1.28;
1680 }
1681 
osd_analogjoy_read(int player,int analog_axis[MAX_ANALOG_AXES],InputCode analogjoy_input[MAX_ANALOG_AXES])1682 void osd_analogjoy_read(int player,int analog_axis[MAX_ANALOG_AXES], InputCode analogjoy_input[MAX_ANALOG_AXES])
1683 {
1684     int i;
1685     for (i = 0; i < MAX_ANALOG_AXES; i ++)
1686     {
1687         if (analogjoy[player][i])
1688             analog_axis[i] = convert_analog_scale(analogjoy[player][i]);
1689     }
1690 
1691     analogjoy_input[0] = IPT_AD_STICK_X;
1692     analogjoy_input[1] = IPT_AD_STICK_Y;
1693 }
1694 
osd_customize_inputport_defaults(struct ipd * defaults)1695 void osd_customize_inputport_defaults(struct ipd *defaults)
1696 {
1697 
1698   unsigned int i = 0;
1699   default_inputs = defaults;
1700 
1701   for( ; default_inputs[i].type != IPT_END; ++i)
1702   {
1703     struct ipd *entry = &default_inputs[i];
1704 
1705     if(options.dual_joysticks)
1706     {
1707       switch(entry->type)
1708       {
1709          case (IPT_JOYSTICKRIGHT_UP   | IPF_PLAYER1):
1710             seq_set_1(&entry->seq, JOYCODE_2_UP);
1711             break;
1712          case (IPT_JOYSTICKRIGHT_DOWN | IPF_PLAYER1):
1713             seq_set_1(&entry->seq, JOYCODE_2_DOWN);
1714             break;
1715          case (IPT_JOYSTICKRIGHT_LEFT | IPF_PLAYER1):
1716             seq_set_1(&entry->seq, JOYCODE_2_LEFT);
1717             break;
1718          case (IPT_JOYSTICKRIGHT_RIGHT | IPF_PLAYER1):
1719             seq_set_1(&entry->seq, JOYCODE_2_RIGHT);
1720             break;
1721          case (IPT_JOYSTICK_UP   | IPF_PLAYER2):
1722             seq_set_1(&entry->seq, JOYCODE_3_UP);
1723             break;
1724          case (IPT_JOYSTICK_DOWN | IPF_PLAYER2):
1725             seq_set_1(&entry->seq, JOYCODE_3_DOWN);
1726             break;
1727          case (IPT_JOYSTICK_LEFT | IPF_PLAYER2):
1728             seq_set_1(&entry->seq, JOYCODE_3_LEFT);
1729             break;
1730          case (IPT_JOYSTICK_RIGHT | IPF_PLAYER2):
1731             seq_set_1(&entry->seq, JOYCODE_3_RIGHT);
1732             break;
1733          case (IPT_JOYSTICKRIGHT_UP   | IPF_PLAYER2):
1734             seq_set_1(&entry->seq, JOYCODE_4_UP);
1735             break;
1736          case (IPT_JOYSTICKRIGHT_DOWN | IPF_PLAYER2):
1737             seq_set_1(&entry->seq, JOYCODE_4_DOWN);
1738             break;
1739          case (IPT_JOYSTICKRIGHT_LEFT | IPF_PLAYER2):
1740             seq_set_1(&entry->seq, JOYCODE_4_LEFT);
1741             break;
1742          case (IPT_JOYSTICKRIGHT_RIGHT | IPF_PLAYER2):
1743             seq_set_1(&entry->seq, JOYCODE_4_RIGHT);
1744             break;
1745          case (IPT_JOYSTICKLEFT_UP   | IPF_PLAYER2):
1746             seq_set_1(&entry->seq, JOYCODE_3_UP);
1747             break;
1748          case (IPT_JOYSTICKLEFT_DOWN | IPF_PLAYER2):
1749             seq_set_1(&entry->seq, JOYCODE_3_DOWN);
1750             break;
1751          case (IPT_JOYSTICKLEFT_LEFT | IPF_PLAYER2):
1752             seq_set_1(&entry->seq, JOYCODE_3_LEFT);
1753             break;
1754          case (IPT_JOYSTICKLEFT_RIGHT | IPF_PLAYER2):
1755             seq_set_1(&entry->seq, JOYCODE_3_RIGHT);
1756             break;
1757      }
1758     }
1759    }
1760 
1761 }
1762 
1763 /* These calibration functions should never actually be used (as long as needs_calibration returns 0 anyway).*/
osd_joystick_needs_calibration(void)1764 int osd_joystick_needs_calibration(void) { return 0; }
osd_joystick_start_calibration(void)1765 void osd_joystick_start_calibration(void){ }
osd_joystick_calibrate_next(void)1766 const char *osd_joystick_calibrate_next(void) { return 0; }
osd_joystick_calibrate(void)1767 void osd_joystick_calibrate(void) { }
osd_joystick_end_calibration(void)1768 void osd_joystick_end_calibration(void) { }
1769 
1770 
1771 /******************************************************************************
1772 
1773 	Keyboard
1774 
1775 ******************************************************************************/
1776 
1777 extern const struct KeyboardInfo retroKeys[];
1778 int retroKeyState[512];
1779 
osd_get_key_list(void)1780 const struct KeyboardInfo *osd_get_key_list(void)
1781 {
1782   return retroKeys;
1783 }
1784 
osd_is_key_pressed(int keycode)1785 int osd_is_key_pressed(int keycode)
1786 {
1787 	if (options.input_interface == RETRO_DEVICE_JOYPAD)
1788 		return 0;
1789 
1790 	if (keycode < 512 && keycode >= 0)
1791     return retroKeyState[keycode];
1792 
1793   return 0;
1794 }
1795 
1796 
osd_readkey_unicode(int flush)1797 int osd_readkey_unicode(int flush)
1798 {
1799   /* TODO*/
1800   return 0;
1801 }
1802 
1803 /******************************************************************************
1804 
1805 	Keymapping
1806 
1807 ******************************************************************************/
1808 
1809 /* Unassigned keycodes*/
1810 /*	KEYCODE_OPENBRACE, KEYCODE_CLOSEBRACE, KEYCODE_BACKSLASH2, KEYCODE_STOP, KEYCODE_LWIN, KEYCODE_RWIN, KEYCODE_DEL_PAD, KEYCODE_PAUSE,*/
1811 
1812 /* The format for each systems key constants is RETROK_$(TAG) and KEYCODE_$(TAG) */
1813 /* EMIT1(TAG): The tag value is the same between libretro and the core           */
1814 /* EMIT2(RTAG, MTAG): The tag value is different between the two                 */
1815 /* EXITX(TAG): The core has no equivalent key.*/
1816 
1817 #define EMIT2(RETRO, KEY) {(char*)#RETRO, RETROK_##RETRO, KEYCODE_##KEY}
1818 #define EMIT1(KEY) {(char*)#KEY, RETROK_##KEY, KEYCODE_##KEY}
1819 #define EMITX(KEY) {(char*)#KEY, RETROK_##KEY, KEYCODE_OTHER}
1820 
1821 const struct KeyboardInfo retroKeys[] =
1822 {
1823     EMIT1(BACKSPACE),
1824     EMIT1(TAB),
1825     EMITX(CLEAR),
1826 
1827     EMIT1(BACKSPACE),
1828     EMIT1(TAB),
1829     EMITX(CLEAR),
1830     EMIT2(RETURN, ENTER),
1831     EMITX(PAUSE),
1832     EMIT2(ESCAPE, ESC),
1833     EMIT1(SPACE),
1834     EMITX(EXCLAIM),
1835     EMIT2(QUOTEDBL, TILDE),
1836     EMITX(HASH),
1837     EMITX(DOLLAR),
1838     EMITX(AMPERSAND),
1839     EMIT1(QUOTE),
1840     EMITX(LEFTPAREN),
1841     EMITX(RIGHTPAREN),
1842     EMIT1(ASTERISK),
1843     EMIT2(PLUS, EQUALS),
1844     EMIT1(COMMA),
1845     EMIT1(MINUS),
1846     EMITX(PERIOD),
1847     EMIT1(SLASH),
1848 
1849     EMIT1(0), EMIT1(1), EMIT1(2), EMIT1(3), EMIT1(4), EMIT1(5), EMIT1(6), EMIT1(7), EMIT1(8), EMIT1(9),
1850 
1851     EMIT1(COLON),
1852     EMITX(SEMICOLON),
1853     EMITX(LESS),
1854     EMITX(EQUALS),
1855     EMITX(GREATER),
1856     EMITX(QUESTION),
1857     EMITX(AT),
1858     EMITX(LEFTBRACKET),
1859     EMIT1(BACKSLASH),
1860     EMITX(RIGHTBRACKET),
1861     EMITX(CARET),
1862     EMITX(UNDERSCORE),
1863     EMITX(BACKQUOTE),
1864 
1865     EMIT2(a, A), EMIT2(b, B), EMIT2(c, C), EMIT2(d, D), EMIT2(e, E), EMIT2(f, F),
1866     EMIT2(g, G), EMIT2(h, H), EMIT2(i, I), EMIT2(j, J), EMIT2(k, K), EMIT2(l, L),
1867     EMIT2(m, M), EMIT2(n, N), EMIT2(o, O), EMIT2(p, P), EMIT2(q, Q), EMIT2(r, R),
1868     EMIT2(s, S), EMIT2(t, T), EMIT2(u, U), EMIT2(v, V), EMIT2(w, W), EMIT2(x, X),
1869     EMIT2(y, Y), EMIT2(z, Z),
1870 
1871     EMIT2(DELETE, DEL),
1872 
1873     EMIT2(KP0, 0_PAD), EMIT2(KP1, 1_PAD), EMIT2(KP2, 2_PAD), EMIT2(KP3, 3_PAD),
1874     EMIT2(KP4, 4_PAD), EMIT2(KP5, 5_PAD), EMIT2(KP6, 6_PAD), EMIT2(KP7, 7_PAD),
1875     EMIT2(KP8, 8_PAD), EMIT2(KP9, 9_PAD),
1876 
1877     EMITX(KP_PERIOD),
1878     EMIT2(KP_DIVIDE, SLASH_PAD),
1879     EMITX(KP_MULTIPLY),
1880     EMIT2(KP_MINUS, MINUS_PAD),
1881     EMIT2(KP_PLUS, PLUS_PAD),
1882     EMIT2(KP_ENTER, ENTER_PAD),
1883     EMITX(KP_EQUALS),
1884 
1885     EMIT1(UP), EMIT1(DOWN), EMIT1(RIGHT), EMIT1(LEFT),
1886     EMIT1(INSERT), EMIT1(HOME), EMIT1(END), EMIT2(PAGEUP, PGUP), EMIT2(PAGEDOWN, PGDN),
1887 
1888     EMIT1(F1), EMIT1(F2), EMIT1(F3), EMIT1(F4), EMIT1(F5), EMIT1(F6),
1889     EMIT1(F7), EMIT1(F8), EMIT1(F9), EMIT1(F10), EMIT1(F11), EMIT1(F12),
1890     EMITX(F13), EMITX(F14), EMITX(F15),
1891 
1892     EMIT1(NUMLOCK),
1893     EMIT1(CAPSLOCK),
1894     EMIT2(SCROLLOCK, SCRLOCK),
1895     EMIT1(RSHIFT), EMIT1(LSHIFT), EMIT2(RCTRL, RCONTROL), EMIT2(LCTRL, LCONTROL), EMIT1(RALT), EMIT1(LALT),
1896     EMITX(RMETA), EMITX(LMETA), EMITX(LSUPER), EMITX(RSUPER),
1897 
1898     EMITX(MODE),
1899     EMITX(COMPOSE),
1900 
1901     EMITX(HELP),
1902     EMIT2(PRINT, PRTSCR),
1903     EMITX(SYSREQ),
1904     EMITX(BREAK),
1905     EMIT1(MENU),
1906     EMITX(POWER),
1907     EMITX(EURO),
1908     EMITX(UNDO),
1909 
1910     {0, 0, 0}
1911 };
1912