mirror of
https://github.com/libretro/beetle-psx-libretro.git
synced 2024-11-23 00:39:40 +00:00
Implement neGcon controller profile with rumble (#905)
* Implement neGcon controller profile with rumble * Remove hold delay from NeGconRumble analog toggle
This commit is contained in:
parent
a90ceba833
commit
5d3253e783
@ -220,6 +220,7 @@ ifneq ($(HAVE_GRIFFIN), 1)
|
||||
$(CORE_EMU_DIR)/input/justifier.cpp \
|
||||
$(CORE_EMU_DIR)/input/guncon.cpp \
|
||||
$(CORE_EMU_DIR)/input/negcon.cpp \
|
||||
$(CORE_EMU_DIR)/input/negconrumble.cpp \
|
||||
$(CORE_EMU_DIR)/input/memcard.cpp \
|
||||
$(CORE_EMU_DIR)/input/multitap.cpp \
|
||||
$(CORE_EMU_DIR)/input/mouse.cpp
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mednafen/psx/input/justifier.cpp"
|
||||
#include "mednafen/psx/input/guncon.cpp"
|
||||
#include "mednafen/psx/input/negcon.cpp"
|
||||
#include "mednafen/psx/input/negconrumble.cpp"
|
||||
#include "mednafen/psx/input/memcard.cpp"
|
||||
#include "mednafen/psx/input/multitap.cpp"
|
||||
#include "mednafen/psx/input/mouse.cpp"
|
||||
|
253
input.cpp
253
input.cpp
@ -88,8 +88,9 @@ static uint32_t input_type[ MAX_CONTROLLERS ] = {0};
|
||||
#define RETRO_DEVICE_PS_JUSTIFIER RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_LIGHTGUN, 1)
|
||||
#define RETRO_DEVICE_PS_MOUSE RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 0)
|
||||
#define RETRO_DEVICE_PS_NEGCON RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_ANALOG, 3)
|
||||
#define RETRO_DEVICE_PS_NEGCON_RUMBLE RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_ANALOG, 4)
|
||||
|
||||
enum { INPUT_DEVICE_TYPES_COUNT = 1 /*none*/ + 8 }; // <-- update me!
|
||||
enum { INPUT_DEVICE_TYPES_COUNT = 1 /*none*/ + 9 }; // <-- update me!
|
||||
|
||||
static const struct retro_controller_description input_device_types[ INPUT_DEVICE_TYPES_COUNT ] =
|
||||
{
|
||||
@ -101,6 +102,7 @@ static const struct retro_controller_description input_device_types[ INPUT_DEVIC
|
||||
{ "Justifier", RETRO_DEVICE_PS_JUSTIFIER },
|
||||
{ "Mouse", RETRO_DEVICE_PS_MOUSE },
|
||||
{ "neGcon", RETRO_DEVICE_PS_NEGCON },
|
||||
{ "neGcon Rumble", RETRO_DEVICE_PS_NEGCON_RUMBLE },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
@ -779,105 +781,9 @@ void input_update(bool libretro_supports_bitmasks, retro_input_state_t input_sta
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case RETRO_DEVICE_PS_NEGCON:
|
||||
|
||||
// Analog Inputs
|
||||
{
|
||||
uint16_t button_ii = std::max(
|
||||
get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_L2 ),
|
||||
get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_Y )
|
||||
);
|
||||
|
||||
uint16_t button_i = std::max(
|
||||
get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_R2 ),
|
||||
get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_B )
|
||||
);
|
||||
uint16_t left_shoulder = get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_L );
|
||||
|
||||
p_input->u32[ 3 ] = button_i; // Analog button I
|
||||
p_input->u32[ 4 ] = button_ii; // Analog button II
|
||||
p_input->u32[ 5 ] = left_shoulder; // Analog shoulder (left only!)
|
||||
}
|
||||
|
||||
// Twist
|
||||
{
|
||||
int analog_left_x = input_state_cb( iplayer, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT,
|
||||
RETRO_DEVICE_ID_ANALOG_X);
|
||||
|
||||
// Account for deadzone
|
||||
if (analog_left_x > negcon_deadzone)
|
||||
analog_left_x = analog_left_x - negcon_deadzone;
|
||||
else if (analog_left_x < -negcon_deadzone)
|
||||
analog_left_x = analog_left_x + negcon_deadzone;
|
||||
else
|
||||
analog_left_x = 0;
|
||||
|
||||
// Convert to an 'amplitude' [-1.0,1.0]
|
||||
float analog_left_x_amplitude = (float)analog_left_x / (float)(NEGCON_RANGE - negcon_deadzone);
|
||||
|
||||
// Handle 'analog self-calibration'...
|
||||
// NB: This seems pointless, since all it does is arbitrarily
|
||||
// reduce the precision of 'twist' input (making games rather
|
||||
// unplayable). Someone, however, must have thought it was a
|
||||
// good idea at some point, so we'll leave the basic functionality
|
||||
// in place...
|
||||
struct analog_calibration *calibration = &analog_calibration[ iplayer ];
|
||||
if ( enable_analog_calibration )
|
||||
{
|
||||
// Compute the current stick deflection
|
||||
float twist = fabsf(analog_left_x_amplitude);
|
||||
|
||||
// We recalibrate when we find a new max value for the sticks
|
||||
if ( twist > analog_calibration->twist )
|
||||
{
|
||||
analog_calibration->twist = twist;
|
||||
log_cb(RETRO_LOG_DEBUG, "Recalibrating twist, deflection: %f\n", twist);
|
||||
}
|
||||
|
||||
// NOTE: This value was copied from the DualShock code below. Needs confirmation.
|
||||
static const float neGcon_analog_deflection = 1.35f;
|
||||
|
||||
// Now compute the scaling factor to apply to convert the
|
||||
// emulator's controller coordinates to a native neGcon range.
|
||||
float twist_scaling = neGcon_analog_deflection / analog_calibration->twist;
|
||||
|
||||
analog_left_x_amplitude = analog_left_x_amplitude * twist_scaling;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the calibration. Since we only increase the
|
||||
// calibration coordinates we can start with a reasonably
|
||||
// small value.
|
||||
analog_calibration->twist = 0.7;
|
||||
}
|
||||
|
||||
// Safety check
|
||||
// (also fixes range when above 'analog self-calibration' twist_scaling
|
||||
// is applied)
|
||||
analog_left_x_amplitude = analog_left_x_amplitude < -1.0f ? -1.0f : analog_left_x_amplitude;
|
||||
analog_left_x_amplitude = analog_left_x_amplitude > 1.0f ? 1.0f : analog_left_x_amplitude;
|
||||
|
||||
// Adjust response
|
||||
if (negcon_linearity == 2)
|
||||
{
|
||||
if (analog_left_x_amplitude < 0.0)
|
||||
analog_left_x_amplitude = -(analog_left_x_amplitude * analog_left_x_amplitude);
|
||||
else
|
||||
analog_left_x_amplitude = analog_left_x_amplitude * analog_left_x_amplitude;
|
||||
}
|
||||
else if (negcon_linearity == 3)
|
||||
analog_left_x_amplitude = analog_left_x_amplitude * analog_left_x_amplitude * analog_left_x_amplitude;
|
||||
|
||||
// Convert back from an 'amplitude' [-1.0,1.0] to a 'range' [-0x7FFF,0x7FFF]
|
||||
analog_left_x = (int)(analog_left_x_amplitude * NEGCON_RANGE);
|
||||
|
||||
uint32_t twist_left = analog_left_x < 0 ? -analog_left_x : 0;
|
||||
uint32_t twist_right = analog_left_x > 0 ? analog_left_x : 0;
|
||||
|
||||
p_input->u32[ 1 ] = twist_right; // Twist Right
|
||||
p_input->u32[ 2 ] = twist_left; // Twist Left
|
||||
}
|
||||
|
||||
// Digital Buttons
|
||||
{
|
||||
p_input->u8[ 0 ] = 0;
|
||||
@ -914,11 +820,51 @@ void input_update(bool libretro_supports_bitmasks, retro_input_state_t input_sta
|
||||
|
||||
break;
|
||||
|
||||
case RETRO_DEVICE_PS_NEGCON_RUMBLE:
|
||||
|
||||
// Digital Buttons
|
||||
{
|
||||
p_input->u8[ 0 ] = 0;
|
||||
|
||||
if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP ) )
|
||||
p_input->u8[ 0 ] |= ( 1 << 4 ); // Pad-Up
|
||||
if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT ) )
|
||||
p_input->u8[ 0 ] |= ( 1 << 5 ); // Pad-Right
|
||||
if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN ) )
|
||||
p_input->u8[ 0 ] |= ( 1 << 6 ); // Pad-Down
|
||||
if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT ) )
|
||||
p_input->u8[ 0 ] |= ( 1 << 7 ); // Pad-Left
|
||||
if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START ) )
|
||||
p_input->u8[ 0 ] |= ( 1 << 3 ); // Start
|
||||
if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT ) )
|
||||
p_input->u8[ 0 ] |= ( 1 << 0 ); // Select / Analog
|
||||
|
||||
p_input->u8[ 1 ] = 0;
|
||||
|
||||
if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A ) )
|
||||
p_input->u8[ 1 ] |= ( 1 << 5 ); // neGcon A
|
||||
if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X ) )
|
||||
p_input->u8[ 1 ] |= ( 1 << 4 ); // neGcon B
|
||||
/*if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L ) )
|
||||
p_input->u8[ 1 ] |= ( 1 << 2 ); // neGcon L shoulder (digital - non-standard?)
|
||||
*/
|
||||
if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R ) )
|
||||
p_input->u8[ 1 ] |= ( 1 << 3 ); // neGcon R shoulder (digital)
|
||||
/*if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2 ) )
|
||||
p_input->u8[ 1 ] |= ( 1 << 0 ); // neGcon L2 (non-standard?)
|
||||
*/
|
||||
/*if ( input_state_cb( iplayer, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2 ) )
|
||||
p_input->u8[ 1 ] |= ( 1 << 1 ); // neGcon R2 (non-standard?)
|
||||
*/
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // switch ( input_type[ iplayer ] )
|
||||
|
||||
|
||||
//
|
||||
// -- Dual Analog Sticks
|
||||
// -- Analog Inputs
|
||||
|
||||
switch ( input_type[ iplayer ] )
|
||||
{
|
||||
@ -1026,6 +972,109 @@ void input_update(bool libretro_supports_bitmasks, retro_input_state_t input_sta
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case RETRO_DEVICE_PS_NEGCON:
|
||||
case RETRO_DEVICE_PS_NEGCON_RUMBLE:
|
||||
|
||||
// Analog Inputs
|
||||
{
|
||||
uint16_t button_ii = std::max(
|
||||
get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_L2 ),
|
||||
get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_Y )
|
||||
);
|
||||
|
||||
uint16_t button_i = std::max(
|
||||
get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_R2 ),
|
||||
get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_B )
|
||||
);
|
||||
uint16_t left_shoulder = get_analog_button( input_state_cb, iplayer, RETRO_DEVICE_ID_JOYPAD_L );
|
||||
|
||||
p_input->u32[ 3 ] = button_i; // Analog button I
|
||||
p_input->u32[ 4 ] = button_ii; // Analog button II
|
||||
p_input->u32[ 5 ] = left_shoulder; // Analog shoulder (left only!)
|
||||
}
|
||||
|
||||
// Twist
|
||||
{
|
||||
int analog_left_x = input_state_cb( iplayer, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT,
|
||||
RETRO_DEVICE_ID_ANALOG_X);
|
||||
|
||||
// Account for deadzone
|
||||
if (analog_left_x > negcon_deadzone)
|
||||
analog_left_x = analog_left_x - negcon_deadzone;
|
||||
else if (analog_left_x < -negcon_deadzone)
|
||||
analog_left_x = analog_left_x + negcon_deadzone;
|
||||
else
|
||||
analog_left_x = 0;
|
||||
|
||||
// Convert to an 'amplitude' [-1.0,1.0]
|
||||
float analog_left_x_amplitude = (float)analog_left_x / (float)(NEGCON_RANGE - negcon_deadzone);
|
||||
|
||||
// Handle 'analog self-calibration'...
|
||||
// NB: This seems pointless, since all it does is arbitrarily
|
||||
// reduce the precision of 'twist' input (making games rather
|
||||
// unplayable). Someone, however, must have thought it was a
|
||||
// good idea at some point, so we'll leave the basic functionality
|
||||
// in place...
|
||||
struct analog_calibration *calibration = &analog_calibration[ iplayer ];
|
||||
if ( enable_analog_calibration )
|
||||
{
|
||||
// Compute the current stick deflection
|
||||
float twist = fabsf(analog_left_x_amplitude);
|
||||
|
||||
// We recalibrate when we find a new max value for the sticks
|
||||
if ( twist > analog_calibration->twist )
|
||||
{
|
||||
analog_calibration->twist = twist;
|
||||
log_cb(RETRO_LOG_DEBUG, "Recalibrating twist, deflection: %f\n", twist);
|
||||
}
|
||||
|
||||
// NOTE: This value was copied from the DualShock code below. Needs confirmation.
|
||||
static const float neGcon_analog_deflection = 1.35f;
|
||||
|
||||
// Now compute the scaling factor to apply to convert the
|
||||
// emulator's controller coordinates to a native neGcon range.
|
||||
float twist_scaling = neGcon_analog_deflection / analog_calibration->twist;
|
||||
|
||||
analog_left_x_amplitude = analog_left_x_amplitude * twist_scaling;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the calibration. Since we only increase the
|
||||
// calibration coordinates we can start with a reasonably
|
||||
// small value.
|
||||
analog_calibration->twist = 0.7;
|
||||
}
|
||||
|
||||
// Safety check
|
||||
// (also fixes range when above 'analog self-calibration' twist_scaling
|
||||
// is applied)
|
||||
analog_left_x_amplitude = analog_left_x_amplitude < -1.0f ? -1.0f : analog_left_x_amplitude;
|
||||
analog_left_x_amplitude = analog_left_x_amplitude > 1.0f ? 1.0f : analog_left_x_amplitude;
|
||||
|
||||
// Adjust response
|
||||
if (negcon_linearity == 2)
|
||||
{
|
||||
if (analog_left_x_amplitude < 0.0)
|
||||
analog_left_x_amplitude = -(analog_left_x_amplitude * analog_left_x_amplitude);
|
||||
else
|
||||
analog_left_x_amplitude = analog_left_x_amplitude * analog_left_x_amplitude;
|
||||
}
|
||||
else if (negcon_linearity == 3)
|
||||
analog_left_x_amplitude = analog_left_x_amplitude * analog_left_x_amplitude * analog_left_x_amplitude;
|
||||
|
||||
// Convert back from an 'amplitude' [-1.0,1.0] to a 'range' [-0x7FFF,0x7FFF]
|
||||
analog_left_x = (int)(analog_left_x_amplitude * NEGCON_RANGE);
|
||||
|
||||
uint32_t twist_left = analog_left_x < 0 ? -analog_left_x : 0;
|
||||
uint32_t twist_right = analog_left_x > 0 ? analog_left_x : 0;
|
||||
|
||||
p_input->u32[ 1 ] = twist_right; // Twist Right
|
||||
p_input->u32[ 2 ] = twist_left; // Twist Left
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // switch ( input_type[ iplayer ] )
|
||||
|
||||
|
||||
@ -1038,6 +1087,7 @@ void input_update(bool libretro_supports_bitmasks, retro_input_state_t input_sta
|
||||
{
|
||||
|
||||
case RETRO_DEVICE_PS_DUALSHOCK:
|
||||
case RETRO_DEVICE_PS_NEGCON_RUMBLE:
|
||||
|
||||
{
|
||||
// Appears to be correct.
|
||||
@ -1124,6 +1174,11 @@ void retro_set_controller_port_device( unsigned in_port, unsigned device )
|
||||
SetInput( in_port, "negcon", (uint8*)&input_data[ in_port ] );
|
||||
break;
|
||||
|
||||
case RETRO_DEVICE_PS_NEGCON_RUMBLE:
|
||||
log_cb( RETRO_LOG_INFO, "Controller %u: neGcon Rumble\n", (in_port+1) );
|
||||
SetInput( in_port, "negconrumble", (uint8*)&input_data[ in_port ] );
|
||||
break;
|
||||
|
||||
default:
|
||||
log_cb( RETRO_LOG_WARN, "Controller %u: Unsupported Device (%u)\n", (in_port+1), device );
|
||||
SetInput( in_port, "none", (uint8*)&input_data[ in_port ] );
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "input/dualshock.h"
|
||||
#include "input/mouse.h"
|
||||
#include "input/negcon.h"
|
||||
#include "input/negconrumble.h"
|
||||
#include "input/guncon.h"
|
||||
#include "input/justifier.h"
|
||||
|
||||
@ -907,6 +908,12 @@ void FrontIO::SetInput(unsigned int port, const char *type, void *ptr)
|
||||
Devices[port] = Device_Mouse_Create();
|
||||
else if(!strcmp(type, "negcon"))
|
||||
Devices[port] = Device_neGcon_Create();
|
||||
else if(!strcmp(type, "negconrumble"))
|
||||
{
|
||||
char name[256];
|
||||
snprintf(name, 256, "neGcon Rumble on port %u", port + 1);
|
||||
Devices[port] = Device_neGconRumble_Create(std::string(name));
|
||||
}
|
||||
else if(!strcmp(type, "guncon"))
|
||||
Devices[port] = Device_GunCon_Create();
|
||||
else if(!strcmp(type, "justifier"))
|
||||
@ -1120,6 +1127,15 @@ static InputDeviceInfoStruct InputDeviceInfoPSXPort[] =
|
||||
Device_neGcon_IDII,
|
||||
},
|
||||
|
||||
{
|
||||
"negconrumble",
|
||||
"neGcon Rumble",
|
||||
"Namco's unconventional twisty racing-game-oriented gamepad with added rumble interface; NPC-101.",
|
||||
NULL,
|
||||
sizeof(Device_neGconRumble_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_neGconRumble_IDII,
|
||||
},
|
||||
|
||||
{
|
||||
"guncon",
|
||||
"GunCon",
|
||||
|
1094
mednafen/psx/input/negconrumble.cpp
Normal file
1094
mednafen/psx/input/negconrumble.cpp
Normal file
File diff suppressed because it is too large
Load Diff
9
mednafen/psx/input/negconrumble.h
Normal file
9
mednafen/psx/input/negconrumble.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef __MDFN_PSX_INPUT_NEGCONRUMBLE_H
|
||||
#define __MDFN_PSX_INPUT_NEGCONRUMBLE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
InputDevice *Device_neGconRumble_Create(const std::string &name);
|
||||
extern InputDeviceInputInfoStruct Device_neGconRumble_IDII[22];
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user