diff --git a/src/mame.h b/src/mame.h index ac011bd39..0d351210c 100644 --- a/src/mame.h +++ b/src/mame.h @@ -205,6 +205,7 @@ struct GameOptions unsigned active_control_type[MAX_PLAYER_COUNT]; /* register to indicate the default control layout for each player as currently set in the frontend */ bool restrict_4_way; /* simulate 4-way joystick restrictor */ unsigned deadzone; /* analog deadzone in percent. 20 corresponds to 20% */ + unsigned input_button_axis_threshold; /* the percent an analog button must be pressed to register a digital press in the core's internal Analog-Digital conversion */ unsigned tate_mode; int crosshair_enable; diff --git a/src/mame2003/mame2003.c b/src/mame2003/mame2003.c index 272c1ed67..2e57f6d6f 100644 --- a/src/mame2003/mame2003.c +++ b/src/mame2003/mame2003.c @@ -29,7 +29,7 @@ static const struct GameDriver *game_driver; -int running = 0; +bool retro_running = false; int gotFrame; static float delta_samples; int samples_per_frame = 0; @@ -45,26 +45,6 @@ struct ipd *default_inputs; /* pointer the array of structs with default MAME i /* data structures to store and translate keyboard state */ const struct KeyboardInfo retroKeys[]; /* MAME data structure keymapping */ -int retroKeyState[RETROK_LAST] = {0}; /* initialise to zero, polled in retro_run */ - -/* data structures for joystick/retropad state */ -int retroJsState[MAX_PLAYER_COUNT][OSD_INPUT_CODES_PER_PLAYER]= {{0}}; /* initialise to zero, polled in retro_run */ - -/* data structures to store trackball/spinner/mouse coordinates */ -int16_t mouse_x[MAX_PLAYER_COUNT]= {0}; -int16_t mouse_y[MAX_PLAYER_COUNT]= {0}; - -/* temporary variables to convert absolute coordinates polled by pointer fallback, which is used - * as a fallback for libretro frontends without DEVICE_RETRO_MOUSE implementations */ -int16_t prev_pointer_x; -int16_t prev_pointer_y; - -/* data structures to store lightgun coordinates */ -int16_t lightgun_x[MAX_PLAYER_COUNT]= {0}; -int16_t lightgun_y[MAX_PLAYER_COUNT]= {0}; - -/* data structures to store position data for analog joysticks */ -int16_t analogjoy[MAX_PLAYER_COUNT][4]= {0}; retro_log_printf_t log_cb; static struct retro_message frontend_message; @@ -105,6 +85,7 @@ enum CORE_OPTIONS/* controls the order in which core options appear. common, imp OPT_USE_ALT_SOUND, OPT_SHARE_DIAL, OPT_DEADZONE, + OPT_INPUT_BUTTON_AXIS_THRESHOLD, OPT_VECTOR_RESOLUTION, OPT_VECTOR_ANTIALIAS, OPT_VECTOR_BEAM, @@ -151,12 +132,12 @@ static void check_system_specs(void); int get_retropad_code(unsigned osd_code); int get_retromouse_code(unsigned osd_code); int get_retrogun_code(unsigned osd_code); + int get_axis_scaled_abs_value(unsigned joycode); unsigned get_ctrl_ipt_code(unsigned player_number, unsigned standard_code); unsigned encode_osd_joycode(unsigned player_number, unsigned joycode); unsigned decode_osd_joycode(unsigned joycode); - unsigned calc_player_number(unsigned joycode); - int normalize_lightgun(int libretro_coordinate); - int analog_deadzone_rescale(int input); + unsigned calc_port(unsigned joycode); + int rescale_analog(int libretro_coordinate); static void remove_slash (char* temp); @@ -287,43 +268,44 @@ void retro_set_environment(retro_environment_t cb) */ static void init_core_options(void) { - init_default(&default_options[OPT_4WAY], APPNAME"_four_way_emulation", "4-way joystick emulation on 8-way joysticks; disabled|enabled"); + init_default(&default_options[OPT_4WAY], APPNAME"_four_way_emulation", "4-way joystick emulation on 8-way joysticks; disabled|enabled"); #if defined(__IOS__) - init_default(&default_options[OPT_MOUSE_DEVICE], APPNAME"_mouse_device", "X-Y Device; pointer|mouse|lightgun|disabled"); + init_default(&default_options[OPT_MOUSE_DEVICE], APPNAME"_mouse_device", "X-Y Device; pointer|mouse|lightgun|disabled"); #else - init_default(&default_options[OPT_MOUSE_DEVICE], APPNAME"_mouse_device", "X-Y Device; mouse|pointer|lightgun|disabled"); + init_default(&default_options[OPT_MOUSE_DEVICE], APPNAME"_mouse_device", "X-Y Device; mouse|pointer|lightgun|disabled"); #endif - init_default(&default_options[OPT_CROSSHAIR_ENABLED], APPNAME"_crosshair_enabled", "Show Lightgun crosshairs; enabled|disabled"); - init_default(&default_options[OPT_SKIP_DISCLAIMER], APPNAME"_skip_disclaimer", "Skip Disclaimer; disabled|enabled"); - init_default(&default_options[OPT_SKIP_WARNINGS], APPNAME"_skip_warnings", "Skip Warnings; disabled|enabled"); - init_default(&default_options[OPT_DISPLAY_SETUP], APPNAME"_display_setup", "Display MAME menu; disabled|enabled"); - 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"); - 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"); - init_default(&default_options[OPT_ARTWORK], APPNAME"_display_artwork", "Display artwork (Restart core); enabled|disabled"); - init_default(&default_options[OPT_ART_RESOLUTION], APPNAME"_art_resolution", "Artwork resolution multiplier (Restart core); 1|2|3|4|5|6|7|8"); - init_default(&default_options[OPT_ART_OVERLAY_OPACITY], APPNAME"_art_overlay_opacity", "Artwork hardcoded overlay opacity (Restart core); default|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|50|70"); - 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|unibios40|unibios33|unibios20|unibios13|unibios11|unibios10|debug|asia-aes"); - 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"); - init_default(&default_options[OPT_USE_ALT_SOUND], APPNAME"_use_alt_sound", "Use CD soundtrack (Restart core); disabled|enabled"); - init_default(&default_options[OPT_SHARE_DIAL], APPNAME"_dialsharexy", "Share 2 player dial controls across one X/Y device; disabled|enabled"); - init_default(&default_options[OPT_DEADZONE], APPNAME"_deadzone", "Analog deadzone; 20|0|5|10|15|25|30|35|40|45|50|55|60|65|70|75|80|85|90|95"); - init_default(&default_options[OPT_TATE_MODE], APPNAME"_tate_mode", "TATE Mode - Rotating display (Restart core); disabled|enabled"); - init_default(&default_options[OPT_VECTOR_RESOLUTION], APPNAME"_vector_resolution", "Vector resolution (Restart core); 1024x768|640x480|1280x960|1440x1080|1600x1200|1707x1280|original"); - init_default(&default_options[OPT_VECTOR_ANTIALIAS], APPNAME"_vector_antialias", "Vector antialiasing; enabled|disabled"); - init_default(&default_options[OPT_VECTOR_BEAM], APPNAME"_vector_beam_width", "Vector beam width (only with antialiasing); 2|1|1.2|1.4|1.6|1.8|2.5|3|4|5|6|7|8|9|10|11|12"); - init_default(&default_options[OPT_VECTOR_TRANSLUCENCY], APPNAME"_vector_translucency", "Vector translucency; enabled|disabled"); - init_default(&default_options[OPT_VECTOR_FLICKER], APPNAME"_vector_flicker", "Vector flicker; 20|0|10|30|40|50|60|70|80|90|100"); - init_default(&default_options[OPT_VECTOR_INTENSITY], APPNAME"_vector_intensity", "Vector intensity; 1.5|0.5|1|2|2.5|3"); - init_default(&default_options[OPT_NVRAM_BOOTSTRAP], APPNAME"_nvram_bootstraps", "NVRAM Bootstraps; enabled|disabled"); - init_default(&default_options[OPT_SAMPLE_RATE], APPNAME"_sample_rate", "Sample Rate (KHz); 48000|8000|11025|22050|30000|44100|"); - init_default(&default_options[OPT_INPUT_INTERFACE], APPNAME"_input_interface", "Input interface; simultaneous|retropad|keyboard"); - init_default(&default_options[OPT_MAME_REMAPPING], APPNAME"_mame_remapping", "Legacy Remapping (Restart core); enabled|disabled"); - init_default(&default_options[OPT_FRAMESKIP], APPNAME"_frameskip", "Frameskip; 0|1|2|3|4|5"); - 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. */ - 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.*/ - init_default(&default_options[OPT_CHEAT_INPUT_PORTS], APPNAME"_cheat_input_ports", "Dip switch/Cheat input ports; disabled|enabled"); - init_default(&default_options[OPT_MACHINE_TIMING], APPNAME"_machine_timing", "Bypass audio skew (Restart core); enabled|disabled"); - init_default(&default_options[OPT_DIGITAL_JOY_CENTERING], APPNAME"_digital_joy_centering", "Center joystick axis for digital controls; enabled|disabled"); + init_default(&default_options[OPT_CROSSHAIR_ENABLED], APPNAME"_crosshair_enabled", "Show Lightgun crosshairs; enabled|disabled"); + init_default(&default_options[OPT_SKIP_DISCLAIMER], APPNAME"_skip_disclaimer", "Skip Disclaimer; disabled|enabled"); + init_default(&default_options[OPT_SKIP_WARNINGS], APPNAME"_skip_warnings", "Skip Warnings; disabled|enabled"); + init_default(&default_options[OPT_DISPLAY_SETUP], APPNAME"_display_setup", "Display MAME menu; disabled|enabled"); + 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"); + 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"); + init_default(&default_options[OPT_ARTWORK], APPNAME"_display_artwork", "Display artwork (Restart core); enabled|disabled"); + init_default(&default_options[OPT_ART_RESOLUTION], APPNAME"_art_resolution", "Artwork resolution multiplier (Restart core); 1|2|3|4|5|6|7|8"); + init_default(&default_options[OPT_ART_OVERLAY_OPACITY], APPNAME"_art_overlay_opacity", "Artwork hardcoded overlay opacity (Restart core); default|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|50|70"); + 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|unibios40|unibios33|unibios20|unibios13|unibios11|unibios10|debug|asia-aes"); + 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"); + init_default(&default_options[OPT_USE_ALT_SOUND], APPNAME"_use_alt_sound", "Use CD soundtrack (Restart core); disabled|enabled"); + init_default(&default_options[OPT_SHARE_DIAL], APPNAME"_dialsharexy", "Share 2 player dial controls across one X/Y device; disabled|enabled"); + init_default(&default_options[OPT_DEADZONE], APPNAME"_deadzone", "Analog deadzone; 20|0|5|10|15|25|30|35|40|45|50|55|60|65|70|75|80|85|90|95"); + init_default(&default_options[OPT_INPUT_BUTTON_AXIS_THRESHOLD], APPNAME"_input_button_axis_threshold", "Input button axis threshold for analog-to-digital conversion; 50|0|5|10|15|20|25|30|35|40|45|55|60|65|70|75|80|85|90|95"); + init_default(&default_options[OPT_TATE_MODE], APPNAME"_tate_mode", "TATE Mode - Rotating display (Restart core); disabled|enabled"); + init_default(&default_options[OPT_VECTOR_RESOLUTION], APPNAME"_vector_resolution", "Vector resolution (Restart core); 1024x768|640x480|1280x960|1440x1080|1600x1200|1707x1280|original"); + init_default(&default_options[OPT_VECTOR_ANTIALIAS], APPNAME"_vector_antialias", "Vector antialiasing; enabled|disabled"); + init_default(&default_options[OPT_VECTOR_BEAM], APPNAME"_vector_beam_width", "Vector beam width (only with antialiasing); 2|1|1.2|1.4|1.6|1.8|2.5|3|4|5|6|7|8|9|10|11|12"); + init_default(&default_options[OPT_VECTOR_TRANSLUCENCY], APPNAME"_vector_translucency", "Vector translucency; enabled|disabled"); + init_default(&default_options[OPT_VECTOR_FLICKER], APPNAME"_vector_flicker", "Vector flicker; 20|0|10|30|40|50|60|70|80|90|100"); + init_default(&default_options[OPT_VECTOR_INTENSITY], APPNAME"_vector_intensity", "Vector intensity; 1.5|0.5|1|2|2.5|3"); + init_default(&default_options[OPT_NVRAM_BOOTSTRAP], APPNAME"_nvram_bootstraps", "NVRAM Bootstraps; enabled|disabled"); + init_default(&default_options[OPT_SAMPLE_RATE], APPNAME"_sample_rate", "Sample Rate (KHz); 48000|8000|11025|22050|30000|44100|"); + init_default(&default_options[OPT_INPUT_INTERFACE], APPNAME"_input_interface", "Input interface; simultaneous|retropad|keyboard"); + init_default(&default_options[OPT_MAME_REMAPPING], APPNAME"_mame_remapping", "Legacy Remapping (Restart core); enabled|disabled"); + init_default(&default_options[OPT_FRAMESKIP], APPNAME"_frameskip", "Frameskip; 0|1|2|3|4|5"); + 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. */ + 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.*/ + init_default(&default_options[OPT_CHEAT_INPUT_PORTS], APPNAME"_cheat_input_ports", "Dip switch/Cheat input ports; disabled|enabled"); + init_default(&default_options[OPT_MACHINE_TIMING], APPNAME"_machine_timing", "Bypass audio skew (Restart core); enabled|disabled"); + init_default(&default_options[OPT_DIGITAL_JOY_CENTERING], APPNAME"_digital_joy_centering", "Center joystick axis for digital controls; enabled|disabled"); init_default(&default_options[OPT_end], NULL, NULL); set_variables(true); } @@ -605,7 +587,11 @@ static void update_variables(bool first_time) } case OPT_DEADZONE: - options.deadzone = atoi(var.value); + options.deadzone = atoi(var.value); + break; + + case OPT_INPUT_BUTTON_AXIS_THRESHOLD: + options.input_button_axis_threshold = atoi(var.value); break; case OPT_TATE_MODE: @@ -1206,138 +1192,19 @@ int16_t get_pointer_delta(int16_t coord, int16_t *prev_coord) void retro_run (void) { - int port = 0; - const struct KeyboardInfo *thisInput; bool updated = false; - if (running == 0) /* first time through the loop */ - { - running = 1; + if (retro_running == false) /* first time through the loop */ log_cb(RETRO_LOG_DEBUG, LOGPRE "Entering retro_run() for the first time.\n"); - } + poll_cb(); if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) update_variables(false); - /* retroJS */ - /* A combination of the non-keyboard input types into an abstracted MAME joystick */ - - /* begin by blanking the old values */ - for(port = 0; port < MAX_PLAYER_COUNT; port++) - { - int code_idx = 0; - for(code_idx = 0; code_idx < OSD_INPUT_CODES_PER_PLAYER; code_idx++) - retroJsState[port][code_idx] = 0; - - analogjoy[port][0] = 0; - analogjoy[port][1] = 0; - analogjoy[port][2] = 0; - analogjoy[port][3] = 0; - mouse_x[port] = 0; - mouse_y[port] = 0; - lightgun_x[port] = 0; - lightgun_y[port] = 0; - } - - for(port = 0; port < MAX_PLAYER_COUNT; port++) - { - int device_type = options.active_control_type[port]; - int device_parent = get_device_parent(device_type); - - if(device_type == RETRO_DEVICE_NONE) continue; - - /* Standard retropad */ - retroJsState[port][OSD_JOYPAD_B] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B); - retroJsState[port][OSD_JOYPAD_Y] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y); - retroJsState[port][OSD_JOYPAD_SELECT] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT); - retroJsState[port][OSD_JOYPAD_START] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START); - retroJsState[port][OSD_JOYPAD_UP] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP); - retroJsState[port][OSD_JOYPAD_DOWN] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN); - retroJsState[port][OSD_JOYPAD_LEFT] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT); - retroJsState[port][OSD_JOYPAD_RIGHT] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT); - retroJsState[port][OSD_JOYPAD_A] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A); - retroJsState[port][OSD_JOYPAD_X] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X); - retroJsState[port][OSD_JOYPAD_L] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L); - retroJsState[port][OSD_JOYPAD_R] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R); - retroJsState[port][OSD_JOYPAD_L2] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2); - retroJsState[port][OSD_JOYPAD_R2] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2); - retroJsState[port][OSD_JOYPAD_L3] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3); - retroJsState[port][OSD_JOYPAD_R3] = input_cb(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3); - - /* Analog joystick - read as analog axis and rescale for MAME value range */ - analogjoy[port][0] = analog_deadzone_rescale( input_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) ); - analogjoy[port][1] = analog_deadzone_rescale( input_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) ); - analogjoy[port][2] = analog_deadzone_rescale( input_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) ); - analogjoy[port][3] = analog_deadzone_rescale( input_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) ); - - /* Analog joystick - read as digital button */ - /* If the analog value (normalized for MAME to the range -128, 128) is greater in absolute */ - /* terms than INPUT_BUTTON_AXIS_THRESHOLD, record it as a binary/digital signal. */ - retroJsState[port][OSD_ANALOG_LEFT_NEGATIVE_X] = (analogjoy[port][0] < -INPUT_BUTTON_AXIS_THRESHOLD) ? analogjoy[port][0] : 0; - retroJsState[port][OSD_ANALOG_LEFT_POSITIVE_X] = (analogjoy[port][0] > INPUT_BUTTON_AXIS_THRESHOLD) ? analogjoy[port][0] : 0; - retroJsState[port][OSD_ANALOG_LEFT_NEGATIVE_Y] = (analogjoy[port][1] < -INPUT_BUTTON_AXIS_THRESHOLD) ? analogjoy[port][1] : 0; - retroJsState[port][OSD_ANALOG_LEFT_POSITIVE_Y] = (analogjoy[port][1] > INPUT_BUTTON_AXIS_THRESHOLD) ? analogjoy[port][1] : 0; - retroJsState[port][OSD_ANALOG_RIGHT_NEGATIVE_X] = (analogjoy[port][2] < -INPUT_BUTTON_AXIS_THRESHOLD) ? analogjoy[port][2] : 0; - retroJsState[port][OSD_ANALOG_RIGHT_POSITIVE_X] = (analogjoy[port][2] > INPUT_BUTTON_AXIS_THRESHOLD) ? analogjoy[port][2] : 0; - retroJsState[port][OSD_ANALOG_RIGHT_NEGATIVE_Y] = (analogjoy[port][3] < -INPUT_BUTTON_AXIS_THRESHOLD) ? analogjoy[port][3] : 0; - retroJsState[port][OSD_ANALOG_RIGHT_POSITIVE_Y] = (analogjoy[port][3] > INPUT_BUTTON_AXIS_THRESHOLD) ? analogjoy[port][3] : 0; - - /* Only poll X-Y device if selected by its core option */ - if(options.mouse_device != RETRO_DEVICE_NONE) - { - if(options.mouse_device == RETRO_DEVICE_MOUSE) - { - retroJsState[port][OSD_MOUSE_BUTTON_1] = input_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT); - retroJsState[port][OSD_MOUSE_BUTTON_2] = input_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT); - retroJsState[port][OSD_MOUSE_BUTTON_3] = input_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE); - retroJsState[port][OSD_MOUSE_BUTTON_4] = input_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_BUTTON_4); - retroJsState[port][OSD_MOUSE_BUTTON_5] = input_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_BUTTON_5); - mouse_x[port] = input_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X); - mouse_y[port] = input_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y); - } - else if (options.mouse_device == RETRO_DEVICE_POINTER) - { - bool pointer_pressed = input_cb(port, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED); - retroJsState[port][OSD_MOUSE_BUTTON_1] = pointer_pressed; - mouse_x[port] = pointer_pressed ? get_pointer_delta(input_cb(port, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X), &prev_pointer_x) : 0; - mouse_y[port] = pointer_pressed ? get_pointer_delta(input_cb(port, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y), &prev_pointer_y) : 0; - } - else if (options.mouse_device == RETRO_DEVICE_LIGHTGUN) - { - lightgun_x[port] = normalize_lightgun(input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X)); - lightgun_y[port] = normalize_lightgun(input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y)); - retroJsState[port][OSD_LIGHTGUN_IS_TRIGGER] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_TRIGGER); /*Status Check*/ - retroJsState[port][OSD_LIGHTGUN_RELOAD] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_RELOAD); /*Forced off-screen shot*/ - retroJsState[port][OSD_LIGHTGUN_AUX_A] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_AUX_A); - retroJsState[port][OSD_LIGHTGUN_AUX_B] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_AUX_B); - retroJsState[port][OSD_LIGHTGUN_START] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_START); - retroJsState[port][OSD_LIGHTGUN_SELECT] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SELECT); - retroJsState[port][OSD_LIGHTGUN_AUX_C] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_AUX_C); - retroJsState[port][OSD_LIGHTGUN_DPAD_UP] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP); - retroJsState[port][OSD_LIGHTGUN_DPAD_DOWN] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN); - retroJsState[port][OSD_LIGHTGUN_DPAD_LEFT] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT); - retroJsState[port][OSD_LIGHTGUN_DPAD_RIGHT] = input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT); - - /* simulated lightgun reload hack */ - if(retroJsState[port][OSD_LIGHTGUN_RELOAD]) - { - retroJsState[port][OSD_LIGHTGUN_IS_TRIGGER] = true; - lightgun_x[port] = -128; - lightgun_y[port] = -128; - } - } - } - } - - /* poll libretro keyboard abstraction */ - thisInput = retroKeys; - while(thisInput->name) - { - retroKeyState[thisInput->code] = input_cb(0, RETRO_DEVICE_KEYBOARD, 0, thisInput->code); - thisInput ++; - } - mame_frame(); + + if (retro_running == false) /* first time through the loop */ + retro_running = true; } void retro_unload_game(void) @@ -1820,6 +1687,7 @@ int get_retropad_code(unsigned osd_id) return INT_MAX; /* no match found */ } + /* converts from OSD_ in mame2003.h to the codes from libretro.h * returns INT_MAX if the code is not valid */ @@ -2137,114 +2005,161 @@ const struct JoystickInfo *osd_get_joy_list(void) */ int osd_is_joy_pressed(int joycode) { - if (options.input_interface == RETRO_DEVICE_KEYBOARD) return 0; /* disregard joystick input */ - - unsigned player_number = calc_player_number(joycode); + int retro_code = -1; unsigned osd_code = decode_osd_joycode(joycode); + unsigned player_number = calc_port(joycode); + unsigned port = player_number - 1; + unsigned control_type = options.active_control_type[port]; /*log_cb(RETRO_LOG_DEBUG, "MAME is polling joysticks -- joycode: %i player_number: %i osd_code: %i\n", joycode, player_number, osd_code); */ - return retroJsState[player_number-1][osd_code]; -} + if(options.input_interface == RETRO_DEVICE_KEYBOARD) return 0; /* disregard joystick input */ + if(control_type == RETRO_DEVICE_NONE) return 0; + if(!retro_running) return 0; /* input callback has not yet been polled */ -int osd_is_joystick_axis_code(unsigned joycode) -{ - unsigned osd_code = decode_osd_joycode(joycode); + /**** check for retropad codes ****/ + retro_code = get_retropad_code(osd_code); + if(retro_code != INT_MAX) + { + if(osd_is_joystick_axis_code(joycode)) /* analog axis */ + return 0; /* this function shouldn't be called for analog axis */ + + return input_cb(port, RETRO_DEVICE_JOYPAD, 0, retro_code); + } + + /**** check for mouse button codes ****/ + retro_code = get_retromouse_code(osd_code); + if(retro_code != INT_MAX) + { + if(options.mouse_device == RETRO_DEVICE_MOUSE) + return input_cb(port, RETRO_DEVICE_MOUSE, 0, retro_code); + if (options.mouse_device == RETRO_DEVICE_POINTER && retro_code == RETRO_DEVICE_ID_MOUSE_LEFT) + return input_cb(port, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED); + } + /**** check for lightgun codes ****/ + retro_code = get_retrogun_code(osd_code); + if(retro_code != INT_MAX) + { + if(retro_code == RETRO_DEVICE_ID_LIGHTGUN_TRIGGER) + if(input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_RELOAD)) + return 1; /* lightgun reload hack */ + + return input_cb(port, RETRO_DEVICE_LIGHTGUN, 0, retro_code); + } + + /**** check for simulated/analog-digital codes ****/ if(osd_code >= OSD_ANALOG_LEFT_NEGATIVE_X && osd_code <= OSD_ANALOG_RIGHT_POSITIVE_Y) - return 1; + { + int effective_threshold = round(MAME_ANALOG_MAX * (options.input_button_axis_threshold / 100)); + if(get_axis_scaled_abs_value(joycode) >= effective_threshold) + return 1; + } - return 0; + return 0; /* should not reach this point */ } -unsigned calc_player_number(unsigned joycode) -{ - return (joycode / 1000); -} -unsigned encode_osd_joycode(unsigned player_number, unsigned raw_code) +int get_axis_scaled_abs_value(unsigned joycode) { - if(raw_code >= OSD_INPUT_CODES_PER_PLAYER) - return INT_MAX; + int value = 0; + int port = calc_port(joycode); + int osd_code = decode_osd_joycode(joycode); + int deadzone = round(((float)options.deadzone / 100) * 128); + float deadzone_factor = (float)MAME_ANALOG_MAX / (MAME_ANALOG_MAX - deadzone); - return (raw_code + (player_number * 1000)); -} + switch(osd_code) + { + case OSD_ANALOG_LEFT_NEGATIVE_X: + case OSD_ANALOG_LEFT_POSITIVE_X: + value = rescale_analog( input_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) ); + if(value > deadzone && osd_code == OSD_ANALOG_LEFT_POSITIVE_X) + return value * deadzone_factor; + else if(value < -deadzone && osd_code == OSD_ANALOG_LEFT_NEGATIVE_X) + return abs(value) * deadzone_factor; + return 0; /* below threshold */ + + case OSD_ANALOG_LEFT_NEGATIVE_Y: + case OSD_ANALOG_LEFT_POSITIVE_Y: + value = rescale_analog( input_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) ); + if(value > deadzone && osd_code == OSD_ANALOG_LEFT_POSITIVE_Y) + return value * deadzone_factor; + else if(value < -deadzone && osd_code == OSD_ANALOG_LEFT_NEGATIVE_Y) + return abs(value) * deadzone_factor; + return 0; /* below threshold */ + + case OSD_ANALOG_RIGHT_NEGATIVE_X: + case OSD_ANALOG_RIGHT_POSITIVE_X: + value = rescale_analog( input_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) ); + if(value > deadzone && osd_code == OSD_ANALOG_RIGHT_POSITIVE_X) + return value * deadzone_factor; + else if(value < -deadzone && osd_code == OSD_ANALOG_RIGHT_NEGATIVE_X) + return abs(value) * deadzone_factor; + return 0; /* below threshold */ + + case OSD_ANALOG_RIGHT_NEGATIVE_Y: + case OSD_ANALOG_RIGHT_POSITIVE_Y: + value = rescale_analog( input_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) ); + if(value > deadzone && osd_code == OSD_ANALOG_RIGHT_POSITIVE_Y) + return value * deadzone_factor; + else if(value < -deadzone && osd_code == OSD_ANALOG_RIGHT_NEGATIVE_Y) + return abs(value) * deadzone_factor; + return 0; /* below threshold */ + } -unsigned decode_osd_joycode(unsigned joycode) -{ - return (joycode - (calc_player_number(joycode) * 1000)); + return 0; } +/****************************************************************************** + * osd_analogjoy_read polls analog joystick axes, and sets the value in the + * analog_axis[] array. + * + * int player is an array index, starting at 0 +*******************************************************************************/ void osd_analogjoy_read(int player, int analog_axis[MAX_ANALOG_AXES], InputCode analogjoy_input[MAX_ANALOG_AXES]) { - int i; - int value; + int axis; - for(i = 0; i < MAX_ANALOG_AXES; i ++) + for(axis = 0; axis < MAX_ANALOG_AXES; axis++) { - int osd_code; - value = 0; - if(analogjoy_input[i] != CODE_NONE) - { - osd_code = decode_osd_joycode(analogjoy_input[i]); - - if(osd_code == OSD_ANALOG_LEFT_NEGATIVE_X || osd_code == OSD_ANALOG_LEFT_POSITIVE_X) - value = analogjoy[player][0]; - - else if(osd_code == OSD_ANALOG_LEFT_NEGATIVE_Y || osd_code == OSD_ANALOG_LEFT_POSITIVE_Y) - value = analogjoy[player][1]; + if(analogjoy_input[axis] != CODE_NONE) + analog_axis[axis] = get_axis_scaled_abs_value(analogjoy_input[axis]); + } +} - else if(osd_code == OSD_ANALOG_RIGHT_NEGATIVE_X || osd_code == OSD_ANALOG_RIGHT_POSITIVE_X) - value = analogjoy[player][2]; - else if(osd_code == OSD_ANALOG_RIGHT_NEGATIVE_Y || osd_code == OSD_ANALOG_RIGHT_POSITIVE_Y) - value = analogjoy[player][3]; +int osd_is_joystick_axis_code(unsigned joycode) +{ + unsigned osd_code = decode_osd_joycode(joycode); - /* opposite when reversing axis mapping */ - if((osd_code % 2) == 0) /* if osd_code is an even number */ - value = -value; + if(osd_code >= OSD_ANALOG_LEFT_NEGATIVE_X && osd_code <= OSD_ANALOG_RIGHT_POSITIVE_Y) + return 1; - analog_axis[i]=value; - } - } + return 0; } -int analog_deadzone_rescale(int input) +unsigned calc_port(unsigned joycode) { - static const int TRIGGER_MAX = 0x8000; - int neg_test=0; - float scale; - int trigger_deadzone; - - trigger_deadzone = (32678 * options.deadzone) / 100; - - if (input < 0) { input =abs(input); neg_test=1; } - scale = ((float)TRIGGER_MAX/(float)(TRIGGER_MAX - trigger_deadzone)); + return (joycode / 1000); +} - if ( input > 0 && input > trigger_deadzone ) - { - // Re-scale analog range - float scaled = (input - trigger_deadzone)*scale; - input = round(scaled); - if (input > +32767) - { - input = +32767; - } - input = input / 327.68; - } +unsigned encode_osd_joycode(unsigned player_number, unsigned raw_code) +{ + if(raw_code >= OSD_INPUT_CODES_PER_PLAYER) + return INT_MAX; - else - { - input = 0; - } + return (raw_code + (player_number * 1000)); +} - if (neg_test) input =-abs(input); - return (int) input * 1.28; +unsigned decode_osd_joycode(unsigned joycode) +{ + return (joycode - (calc_port(joycode) * 1000)); } + /****************************************************************************** * * Legacy joystick calibration functions @@ -2281,12 +2196,41 @@ void osd_joystick_end_calibration(void) { } /* osd_track_read expects the OSD to return the relative change in mouse or trackball * coordinates since the last reading. If the user has set their mouse type to * `pointer` in the core options, its coordinates are translated from absolute to - * relative coordinates before being stored in `mouse_x[]`. + * relative coordinates before being returned. + * + * int player is an array index, starting at 0 */ void osd_trak_read(int player, int *deltax, int *deltay) { - *deltax = mouse_x[player]; - *deltay = mouse_y[player]; + int control_type = options.active_control_type[player]; + int parent_type = get_device_parent(control_type); + + if(options.mouse_device == RETRO_DEVICE_NONE || parent_type == RETRO_DEVICE_LIGHTGUN) + { + *deltax = 0; + *deltay = 0; + return; + } + + if(options.mouse_device == RETRO_DEVICE_MOUSE) + { + *deltax = input_cb(player, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X); + *deltay = input_cb(player, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y); + return; + } + + /* RETRO_DEVICE_POINTER fallback for frontends without a DEVICE_RETRO_MOUSE implementation */ + if (options.mouse_device == RETRO_DEVICE_POINTER && input_cb(player, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED)) + { /* pointer is pressed, so location can be used */ + static int16_t prev_pointer_x; /* temporary variables to convert absolute coordinates polled by pointer to relative mouse coordinates */ + static int16_t prev_pointer_y; + *deltax = get_pointer_delta(input_cb(player, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X), &prev_pointer_x); + *deltay = get_pointer_delta(input_cb(player, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y), &prev_pointer_y); + return; + } + + *deltax = 0; + *deltay = 0; } @@ -2305,32 +2249,35 @@ void osd_trak_read(int player, int *deltax, int *deltay) * When the OSD lightgun returns 0, control passes through to the analog joystick, * and mouse, in that order. In other words, when the OSD lightgun returns a * value it overrides both mouse & analog joystick. + * + * int player is an array index, starting at 0 *******************************************************************************/ void osd_lightgun_read(int player, int *deltax, int *deltay) { - *deltax = lightgun_x[player]; - *deltay = lightgun_y[player]; -} + unsigned control_type = options.active_control_type[player]; + unsigned parent_type = get_device_parent(control_type); -/****************************************************************************** - * normalize_lightgun converts between the libretro coordinate system and the - * MAME OSD coordinate system. - * - * RETRO_DEVICE_LIGHTGUN reports X/Y coordinates in screen space in the range - * [-0x8000, 0x7fff] in both axes, with zero being center and -0x8000 being - * out of bounds. - * - * Meanwhile the MAME OSD uses delta from the middle of the screen - * when the lightgun is fired and 0 when the gun is inactive. The value returned - * by the OSD layer should be -128 to 128, same as analog joysticks. - ******************************************************************************/ -int normalize_lightgun(int libretro_coordinate) -{ - if (libretro_coordinate == 0 || libretro_coordinate == LIBRETRO_ANALOG_MIN) return 0; + if(parent_type != RETRO_DEVICE_LIGHTGUN) + { + *deltax = 0; + *deltay = 0; + return; + } + else + { + if(input_cb(player, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_RELOAD)) /*Forced off-screen shot*/ + { + *deltax = -128; + *deltay = -128; + return; /* lightgun simulated reload hack */ + } + } - return round(((float)libretro_coordinate / LIBRETRO_ANALOG_MAX) * ANALOG_MAX); + *deltax = rescale_analog(input_cb(player, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X)); + *deltay = rescale_analog(input_cb(player, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y)); } + /****************************************************************************** Keyboard @@ -2345,11 +2292,11 @@ const struct KeyboardInfo *osd_get_key_list(void) int osd_is_key_pressed(int keycode) { - if (options.input_interface == RETRO_DEVICE_JOYPAD) - return 0; /* do not return keyboard input if the core option is set to retropad/joystick only */ + if(!retro_running) return 0; /* input callback has not yet been polled */ + if(options.input_interface == RETRO_DEVICE_JOYPAD) return 0; /* core option is set to retropad/joystick only */ - if (keycode < RETROK_LAST && keycode >= 0) - return retroKeyState[keycode]; + if(keycode < RETROK_LAST && keycode >= 0) + return input_cb(0, RETRO_DEVICE_KEYBOARD, 0, keycode); log_cb(RETRO_LOG_WARN, LOGPRE "Invalid OSD keycode received: %i\n", keycode); /* this should not happen when keycodes are properly registered with MAME */ return 0; @@ -2493,6 +2440,30 @@ const struct KeyboardInfo retroKeys[] = ******************************************************************************/ +/****************************************************************************** + * rescale_analog converts between the libretro coordinate system and the + * MAME OSD coordinate system. + * + * RETRO_DEVICE_LIGHTGUN report X/Y coordinates in the range [-0x8000, 0x7fff] + * in both axes, with zero being center and -0x8000 being out of bounds. + * RETRO_DEVICE_ANALOG uses the same [-0x8000, 0x7fff] range. + * + * For lightguns, the MAME OSD uses delta from the middle of the screen when + * the lightgun is fired, and 0 when the gun is inactive with a range of + * -128 to 128. MAME OSD uses this same range for analog joysticks. + * + * Therefore we can use a common function to scale input from lightguns and + * analog controls. + ******************************************************************************/ +int rescale_analog(int libretro_coordinate) +{ + static const float scale_factor = (float)MAME_ANALOG_MAX / LIBRETRO_ANALOG_MAX; + + if (libretro_coordinate == 0 || libretro_coordinate == LIBRETRO_ANALOG_MIN) return 0; + + return round(scale_factor * libretro_coordinate); +} + /* inptport.c defines general purpose defaults for key and joystick bindings which * may be further adjusted by the OS dependent code to better match the available * keyboard, e.g. one could map pause to the Pause key instead of P, or snapshot diff --git a/src/mame2003/mame2003.h b/src/mame2003/mame2003.h index 759926182..708ba95bb 100644 --- a/src/mame2003/mame2003.h +++ b/src/mame2003/mame2003.h @@ -55,17 +55,16 @@ extern "C" { ***************************************************************************/ -#define APPNAME "mame2003-plus" +#define APPNAME "mame2003-plus" -#define FRAMES_PER_FPS_UPDATE 12 -#define MAX_GFX_ELEMENTS 32 -#define MAX_MEMORY_REGIONS 32 +#define FRAMES_PER_FPS_UPDATE 12 +#define MAX_GFX_ELEMENTS 32 +#define MAX_MEMORY_REGIONS 32 -#define INPUT_BUTTON_AXIS_THRESHOLD 64 -#define LIBRETRO_ANALOG_MIN -32768 -#define LIBRETRO_ANALOG_MAX 32767 -#define ANALOG_MIN -128 -#define ANALOG_MAX 128 +#define LIBRETRO_ANALOG_MIN -32768 +#define LIBRETRO_ANALOG_MAX 32767 +#define MAME_ANALOG_MIN -128 +#define MAME_ANALOG_MAX 128 enum {