mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
ControllerInterface/Wiimote: Provide fallback values for extensions with bad calibration data.
This commit is contained in:
parent
ed32a2a1fe
commit
5299e902aa
@ -14,6 +14,7 @@
|
|||||||
#include "Common/BitUtils.h"
|
#include "Common/BitUtils.h"
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
|
#include "Common/MathUtil.h"
|
||||||
#include "InputCommon/ControlReference/ExpressionParser.h"
|
#include "InputCommon/ControlReference/ExpressionParser.h"
|
||||||
#include "InputCommon/ControllerInterface/Device.h"
|
#include "InputCommon/ControllerInterface/Device.h"
|
||||||
|
|
||||||
@ -37,6 +38,20 @@ struct TwoPointCalibration
|
|||||||
TwoPointCalibration() = default;
|
TwoPointCalibration() = default;
|
||||||
TwoPointCalibration(const T& zero_, const T& max_) : zero{zero_}, max{max_} {}
|
TwoPointCalibration(const T& zero_, const T& max_) : zero{zero_}, max{max_} {}
|
||||||
|
|
||||||
|
// Sanity check is that max and zero are not equal.
|
||||||
|
constexpr bool IsSane() const
|
||||||
|
{
|
||||||
|
if constexpr (std::is_arithmetic_v<T>)
|
||||||
|
{
|
||||||
|
return max != zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return std::equal(std::begin(max.data), std::end(max.data), std::begin(zero.data),
|
||||||
|
std::not_equal_to<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr size_t BITS_OF_PRECISION = Bits;
|
static constexpr size_t BITS_OF_PRECISION = Bits;
|
||||||
|
|
||||||
T zero;
|
T zero;
|
||||||
@ -53,6 +68,28 @@ struct ThreePointCalibration
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanity check is that min and max are on opposite sides of the zero value.
|
||||||
|
constexpr bool IsSane() const
|
||||||
|
{
|
||||||
|
if constexpr (std::is_arithmetic_v<T>)
|
||||||
|
{
|
||||||
|
return MathUtil::Sign(zero - min) * MathUtil::Sign(zero - max) == -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i != std::size(zero.data); ++i)
|
||||||
|
{
|
||||||
|
if (MathUtil::Sign(zero.data[i] - min.data[i]) *
|
||||||
|
MathUtil::Sign(zero.data[i] - max.data[i]) !=
|
||||||
|
-1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr size_t BITS_OF_PRECISION = Bits;
|
static constexpr size_t BITS_OF_PRECISION = Bits;
|
||||||
|
|
||||||
T min;
|
T min;
|
||||||
|
@ -610,22 +610,27 @@ void Device::RunTasks()
|
|||||||
|
|
||||||
WiimoteEmu::UpdateCalibrationDataChecksum(calibration_data, 2);
|
WiimoteEmu::UpdateCalibrationDataChecksum(calibration_data, 2);
|
||||||
|
|
||||||
|
Checksum checksum = Checksum::Good;
|
||||||
|
|
||||||
if (read_checksum != std::pair(calibration_data[CALIBRATION_SIZE - 2],
|
if (read_checksum != std::pair(calibration_data[CALIBRATION_SIZE - 2],
|
||||||
calibration_data[CALIBRATION_SIZE - 1]))
|
calibration_data[CALIBRATION_SIZE - 1]))
|
||||||
{
|
{
|
||||||
// We could potentially try another block or call the extension unusable.
|
// We could potentially try another block or call the extension unusable.
|
||||||
WARN_LOG(WIIMOTE, "WiiRemote: Bad extension calibration checksum.");
|
WARN_LOG(WIIMOTE, "WiiRemote: Bad extension calibration checksum.");
|
||||||
|
checksum = Checksum::Bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_extension_id == ExtensionID::Nunchuk)
|
if (m_extension_id == ExtensionID::Nunchuk)
|
||||||
{
|
{
|
||||||
m_nunchuk_state.SetCalibrationData(
|
m_nunchuk_state.SetCalibrationData(
|
||||||
Common::BitCastPtr<WiimoteEmu::Nunchuk::CalibrationData>(calibration_data.data()));
|
Common::BitCastPtr<WiimoteEmu::Nunchuk::CalibrationData>(calibration_data.data()),
|
||||||
|
checksum);
|
||||||
}
|
}
|
||||||
else if (m_extension_id == ExtensionID::Classic)
|
else if (m_extension_id == ExtensionID::Classic)
|
||||||
{
|
{
|
||||||
m_classic_state.SetCalibrationData(
|
m_classic_state.SetCalibrationData(
|
||||||
Common::BitCastPtr<WiimoteEmu::Classic::CalibrationData>(calibration_data.data()));
|
Common::BitCastPtr<WiimoteEmu::Classic::CalibrationData>(calibration_data.data()),
|
||||||
|
checksum);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -730,24 +735,76 @@ void Device::MotionPlusState::SetCalibrationData(
|
|||||||
calibration->slow = data.slow;
|
calibration->slow = data.slow;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::NunchukState::SetCalibrationData(const WiimoteEmu::Nunchuk::CalibrationData& data)
|
Device::NunchukState::Calibration::Calibration() : accel{}, stick{}
|
||||||
|
{
|
||||||
|
accel.zero.data.fill(1 << (accel.BITS_OF_PRECISION - 1));
|
||||||
|
// Approximate 1G value per WiiBrew:
|
||||||
|
accel.max.data.fill(740);
|
||||||
|
|
||||||
|
stick.zero.data.fill(1 << (stick.BITS_OF_PRECISION - 1));
|
||||||
|
stick.max.data.fill((1 << stick.BITS_OF_PRECISION) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::NunchukState::SetCalibrationData(const WiimoteEmu::Nunchuk::CalibrationData& data,
|
||||||
|
Checksum checksum)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WIIMOTE, "WiiRemote: Set Nunchuk calibration.");
|
DEBUG_LOG(WIIMOTE, "WiiRemote: Set Nunchuk calibration.");
|
||||||
|
|
||||||
calibration.emplace();
|
calibration.emplace();
|
||||||
|
|
||||||
calibration->stick = data.GetStick();
|
if (checksum == Checksum::Bad)
|
||||||
calibration->accel = data.GetAccel();
|
return;
|
||||||
|
|
||||||
|
// Genuine Nunchuks have been observed with "min" and "max" values of zero.
|
||||||
|
// We catch that here and fall back to "full range" calibration.
|
||||||
|
const auto stick_calibration = data.GetStick();
|
||||||
|
if (stick_calibration.IsSane())
|
||||||
|
calibration->stick = stick_calibration;
|
||||||
|
else
|
||||||
|
WARN_LOG(WIIMOTE, "WiiRemote: Nunchuk stick calibration is not sane. Using fallback values.");
|
||||||
|
|
||||||
|
// No known reports of bad accelerometer calibration but we'll handle it just in case.
|
||||||
|
const auto accel_calibration = data.GetAccel();
|
||||||
|
if (accel_calibration.IsSane())
|
||||||
|
calibration->accel = accel_calibration;
|
||||||
|
else
|
||||||
|
WARN_LOG(WIIMOTE, "WiiRemote: Nunchuk accel calibration is not sane. Using fallback values.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::ClassicState::SetCalibrationData(const WiimoteEmu::Classic::CalibrationData& data)
|
Device::ClassicState::Calibration::Calibration()
|
||||||
|
: left_stick{}, right_stick{}, left_trigger{}, right_trigger{}
|
||||||
|
{
|
||||||
|
left_stick.zero.data.fill(1 << (left_stick.BITS_OF_PRECISION - 1));
|
||||||
|
left_stick.max.data.fill((1 << left_stick.BITS_OF_PRECISION) - 1);
|
||||||
|
|
||||||
|
right_stick.zero.data.fill(1 << (right_stick.BITS_OF_PRECISION - 1));
|
||||||
|
right_stick.max.data.fill((1 << right_stick.BITS_OF_PRECISION) - 1);
|
||||||
|
|
||||||
|
left_trigger.max = (1 << left_trigger.BITS_OF_PRECISION) - 1;
|
||||||
|
right_trigger.max = (1 << right_trigger.BITS_OF_PRECISION) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::ClassicState::SetCalibrationData(const WiimoteEmu::Classic::CalibrationData& data,
|
||||||
|
Checksum checksum)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WIIMOTE, "WiiRemote: Set Classic Controller calibration.");
|
DEBUG_LOG(WIIMOTE, "WiiRemote: Set Classic Controller calibration.");
|
||||||
|
|
||||||
calibration.emplace();
|
calibration.emplace();
|
||||||
|
|
||||||
calibration->left_stick = data.GetLeftStick();
|
if (checksum == Checksum::Bad)
|
||||||
calibration->right_stick = data.GetRightStick();
|
return;
|
||||||
|
|
||||||
|
const auto left_stick_calibration = data.GetLeftStick();
|
||||||
|
if (left_stick_calibration.IsSane())
|
||||||
|
calibration->left_stick = left_stick_calibration;
|
||||||
|
else
|
||||||
|
WARN_LOG(WIIMOTE, "WiiRemote: CC left stick calibration is not sane. Using fallback values.");
|
||||||
|
|
||||||
|
const auto right_stick_calibration = data.GetRightStick();
|
||||||
|
if (right_stick_calibration.IsSane())
|
||||||
|
calibration->right_stick = right_stick_calibration;
|
||||||
|
else
|
||||||
|
WARN_LOG(WIIMOTE, "WiiRemote: CC right stick calibration is not sane. Using fallback values.");
|
||||||
|
|
||||||
calibration->left_trigger = data.GetLeftTrigger();
|
calibration->left_trigger = data.GetLeftTrigger();
|
||||||
calibration->right_trigger = data.GetRightTrigger();
|
calibration->right_trigger = data.GetRightTrigger();
|
||||||
|
@ -46,6 +46,12 @@ private:
|
|||||||
Unsupported,
|
Unsupported,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Checksum
|
||||||
|
{
|
||||||
|
Good,
|
||||||
|
Bad,
|
||||||
|
};
|
||||||
|
|
||||||
class MotionPlusState
|
class MotionPlusState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -70,7 +76,7 @@ private:
|
|||||||
{
|
{
|
||||||
using CalibrationData = WiimoteEmu::Nunchuk::CalibrationData;
|
using CalibrationData = WiimoteEmu::Nunchuk::CalibrationData;
|
||||||
|
|
||||||
void SetCalibrationData(const CalibrationData&);
|
void SetCalibrationData(const CalibrationData&, Checksum);
|
||||||
void ProcessData(const WiimoteEmu::Nunchuk::DataFormat&);
|
void ProcessData(const WiimoteEmu::Nunchuk::DataFormat&);
|
||||||
|
|
||||||
Common::Vec2 stick = {};
|
Common::Vec2 stick = {};
|
||||||
@ -80,6 +86,8 @@ private:
|
|||||||
|
|
||||||
struct Calibration
|
struct Calibration
|
||||||
{
|
{
|
||||||
|
Calibration();
|
||||||
|
|
||||||
CalibrationData::AccelCalibration accel;
|
CalibrationData::AccelCalibration accel;
|
||||||
CalibrationData::StickCalibration stick;
|
CalibrationData::StickCalibration stick;
|
||||||
};
|
};
|
||||||
@ -91,7 +99,7 @@ private:
|
|||||||
{
|
{
|
||||||
using CalibrationData = WiimoteEmu::Classic::CalibrationData;
|
using CalibrationData = WiimoteEmu::Classic::CalibrationData;
|
||||||
|
|
||||||
void SetCalibrationData(const CalibrationData&);
|
void SetCalibrationData(const CalibrationData&, Checksum);
|
||||||
void ProcessData(const WiimoteEmu::Classic::DataFormat&);
|
void ProcessData(const WiimoteEmu::Classic::DataFormat&);
|
||||||
|
|
||||||
std::array<Common::Vec2, 2> sticks = {};
|
std::array<Common::Vec2, 2> sticks = {};
|
||||||
@ -101,6 +109,8 @@ private:
|
|||||||
|
|
||||||
struct Calibration
|
struct Calibration
|
||||||
{
|
{
|
||||||
|
Calibration();
|
||||||
|
|
||||||
CalibrationData::StickCalibration left_stick;
|
CalibrationData::StickCalibration left_stick;
|
||||||
CalibrationData::StickCalibration right_stick;
|
CalibrationData::StickCalibration right_stick;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user