diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 6623774d92..889a58b017 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -722,6 +722,16 @@ static void check_variables(CoreParameter &coreParam) g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CIRCLE; } + var.key = "ppsspp_analog_is_circular"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bAnalogIsCircular = false; + else + g_Config.bAnalogIsCircular = true; + } + + var.key = "ppsspp_internal_resolution"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { @@ -1534,6 +1544,31 @@ static void retro_input(void) float y_left = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / -32767.0f; float x_right = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 32767.0f; float y_right = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / -32767.0f; + + __CtrlSetAnalogXY(CTRL_STICK_LEFT, x_left, y_left); + __CtrlSetAnalogXY(CTRL_STICK_RIGHT, x_right, y_right); + + // Analog circle vs square gate compensation + // copied from ControlMapper.cpp's ConvertAnalogStick function + const bool isCircular = g_Config.bAnalogIsCircular; + + float norm = std::max(fabsf(x_left), fabsf(y_left)); + + if (norm == 0.0f) + return; + + if (isCircular) { + float newNorm = sqrtf(x_left * x_left + y_left * y_left); + float factor = newNorm / norm; + x_left *= factor; + y_left *= factor; + norm = newNorm; + } + + float mappedNorm = norm; + x_left = std::clamp(x_left / norm * mappedNorm, -1.0f, 1.0f); + y_left = std::clamp(y_left / norm * mappedNorm, -1.0f, 1.0f); + __CtrlSetAnalogXY(CTRL_STICK_LEFT, x_left, y_left); __CtrlSetAnalogXY(CTRL_STICK_RIGHT, x_right, y_right); } diff --git a/libretro/libretro_core_options.h b/libretro/libretro_core_options.h index ede76d29e2..d0f7c22c72 100644 --- a/libretro/libretro_core_options.h +++ b/libretro/libretro_core_options.h @@ -261,6 +261,16 @@ struct retro_core_option_v2_definition option_defs_us[] = { }, "Cross" }, + { + "ppsspp_analog_is_circular", + "Analog Circle vs Square Gate Compensation", + NULL, + NULL, + NULL, + "system", + BOOL_OPTIONS, + "disabled" + }, { "ppsspp_internal_resolution", "Internal Resolution (Restart)",