diff --git a/Source/Core/Core/HW/SI/SI_DeviceGCSteeringWheel.cpp b/Source/Core/Core/HW/SI/SI_DeviceGCSteeringWheel.cpp index c72cddc1dc..3fe0a3230f 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceGCSteeringWheel.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceGCSteeringWheel.cpp @@ -4,6 +4,8 @@ #include "Core/HW/SI/SI_DeviceGCSteeringWheel.h" +#include +#include #include #include "Common/CommonTypes.h" @@ -57,13 +59,37 @@ bool CSIDevice_GCSteeringWheel::GetData(u32& hi, u32& low) low = (u8)pad_status.triggerRight; // All 8 bits low |= (u32)((u8)pad_status.triggerLeft << 8); // All 8 bits - // The GC Steering Wheel appears to have combined pedals - // (both the Accelerate and Brake pedals are mapped to a single axis) - // We use the stickY axis for the pedals. - if (pad_status.stickY < 128) - low |= (u32)((u8)(255 - ((pad_status.stickY & 0x7f) * 2)) << 16); // All 8 bits (Brake) - if (pad_status.stickY >= 128) - low |= (u32)((u8)((pad_status.stickY & 0x7f) * 2) << 24); // All 8 bits (Accelerate) + // The GC Steering Wheel has 8 bit values for both the accelerator/brake. + // Our mapping UI and GCPadEmu class weren't really designed to provide + // input data other than what the regular GC controller has. + // + // Without a big redesign we really don't have a choice but to + // use the analog stick values for accelerator/brake. + // + // Main-stick: up:accelerator / down:brake + // + // But that doesn't allow the user to press both at the same time. + // so also provide the opposite functionality on the c-stick. + // + // C-stick: up:brake / down:accelerator + + // Use either the upper-half of main-stick or lower-half of c-stick for accelerator. + const int accel_value = std::max(pad_status.stickY - GCPadStatus::MAIN_STICK_CENTER_Y, + GCPadStatus::C_STICK_CENTER_Y - pad_status.substickY); + + // Use either the upper-half of c-stick or lower-half of main-stick for brake. + const int brake_value = std::max(pad_status.substickY - GCPadStatus::C_STICK_CENTER_Y, + GCPadStatus::MAIN_STICK_CENTER_Y - pad_status.stickY); + + // We must double these values because we are mapping half of a stick range to a 0..255 value. + // We're only getting half the precison we could potentially have, + // but we'll have to redesign our gamecube controller input to fix that. + + // All 8 bits (Accelerate) + low |= u32(std::clamp(accel_value * 2, 0, 0xff)) << 24; + + // All 8 bits (Brake) + low |= u32(std::clamp(brake_value * 2, 0, 0xff)) << 16; HandleButtonCombos(pad_status); }