diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 39d7a180c..bc48cb109 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -135,9 +136,25 @@ void Module::UpdatePadCallback(u64 userdata, s64 cycles_late) { // Get current circle pad position and update circle pad direction float circle_pad_x_f, circle_pad_y_f; std::tie(circle_pad_x_f, circle_pad_y_f) = circle_pad->GetStatus(); - constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position - s16 circle_pad_x = static_cast(circle_pad_x_f * MAX_CIRCLEPAD_POS); - s16 circle_pad_y = static_cast(circle_pad_y_f * MAX_CIRCLEPAD_POS); + + // xperia64: 0x9A seems to be the calibrated limit of the circle pad + // Verified by using Input Redirector with very large-value digital inputs + // on the circle pad and calibrating using the system settings application + constexpr int MAX_CIRCLEPAD_POS = 0x9A; // Max value for a circle pad position + + // These are rounded rather than truncated on actual hardware + s16 circle_pad_new_x = static_cast(std::roundf(circle_pad_x_f * MAX_CIRCLEPAD_POS)); + s16 circle_pad_new_y = static_cast(std::roundf(circle_pad_y_f * MAX_CIRCLEPAD_POS)); + s16 circle_pad_x = + (circle_pad_new_x + std::accumulate(circle_pad_old_x.begin(), circle_pad_old_x.end(), 0)) / + CIRCLE_PAD_AVERAGING; + s16 circle_pad_y = + (circle_pad_new_y + std::accumulate(circle_pad_old_y.begin(), circle_pad_old_y.end(), 0)) / + CIRCLE_PAD_AVERAGING; + circle_pad_old_x.erase(circle_pad_old_x.begin()); + circle_pad_old_x.push_back(circle_pad_new_x); + circle_pad_old_y.erase(circle_pad_old_y.begin()); + circle_pad_old_y.push_back(circle_pad_new_y); Core::Movie::GetInstance().HandlePadAndCircleStatus(state, circle_pad_x, circle_pad_y); diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 18e7aa3f3..f07f764a7 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "common/bit_field.h" #include "common/common_funcs.h" @@ -318,6 +319,14 @@ private: // Storing this here was necessary for emulation specific tasks like cheats or scripting. PadState state; + // xperia64: These are used to averate the previous N raw circle pad inputs with the current raw + // input to simulate the sluggishness of a real 3DS circle pad + // The Theatrhythm games rely on the circle pad being fairly slow to move, and from empircal + // testing, need a minimum of 3 averaging to not drop inputs + static constexpr s16 CIRCLE_PAD_AVERAGING = 3; + std::vector circle_pad_old_x = std::vector(CIRCLE_PAD_AVERAGING - 1, 0); + std::vector circle_pad_old_y = std::vector(CIRCLE_PAD_AVERAGING - 1, 0); + u32 next_pad_index = 0; u32 next_touch_index = 0; u32 next_accelerometer_index = 0;