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