early-access version 3573
This commit is contained in:
parent
17b9efbffd
commit
8b74a66045
11 changed files with 92 additions and 25 deletions
|
@ -1,7 +1,7 @@
|
|||
yuzu emulator early access
|
||||
=============
|
||||
|
||||
This is the source code for early-access 3571.
|
||||
This is the source code for early-access 3573.
|
||||
|
||||
## Legal Notice
|
||||
|
||||
|
|
|
@ -688,6 +688,12 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage
|
|||
ReloadInput();
|
||||
}
|
||||
|
||||
void EmulatedController::StartMotionCalibration() {
|
||||
for (ControllerMotionInfo& motion : controller.motion_values) {
|
||||
motion.emulated.Calibrate();
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index,
|
||||
Common::UUID uuid) {
|
||||
if (index >= controller.button_values.size()) {
|
||||
|
|
|
@ -290,6 +290,9 @@ public:
|
|||
*/
|
||||
void SetMotionParam(std::size_t index, Common::ParamPackage param);
|
||||
|
||||
/// Auto calibrates the current motion devices
|
||||
void StartMotionCalibration();
|
||||
|
||||
/// Returns the latest button status from the controller with parameters
|
||||
ButtonValues GetButtonsValues() const;
|
||||
|
||||
|
|
|
@ -37,11 +37,17 @@ void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
|
|||
gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue);
|
||||
gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue);
|
||||
|
||||
// Auto adjust drift to minimize drift
|
||||
// Auto adjust gyro_bias to minimize drift
|
||||
if (!IsMoving(IsAtRestRelaxed)) {
|
||||
gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f);
|
||||
}
|
||||
|
||||
// Adjust drift when calibration mode is enabled
|
||||
if (calibration_mode) {
|
||||
gyro_bias = (gyro_bias * 0.99f) + (gyroscope * 0.01f);
|
||||
StopCalibration();
|
||||
}
|
||||
|
||||
if (gyro.Length() < gyro_threshold * user_gyro_threshold) {
|
||||
gyro = {};
|
||||
} else {
|
||||
|
@ -107,6 +113,19 @@ void MotionInput::UpdateRotation(u64 elapsed_time) {
|
|||
rotations += gyro * sample_period;
|
||||
}
|
||||
|
||||
void MotionInput::Calibrate() {
|
||||
calibration_mode = true;
|
||||
calibration_counter = 0;
|
||||
}
|
||||
|
||||
void MotionInput::StopCalibration() {
|
||||
if (calibration_counter++ > CalibrationSamples) {
|
||||
calibration_mode = false;
|
||||
ResetQuaternion();
|
||||
ResetRotations();
|
||||
}
|
||||
}
|
||||
|
||||
// Based on Madgwick's implementation of Mayhony's AHRS algorithm.
|
||||
// https://github.com/xioTechnologies/Open-Source-AHRS-With-x-IMU/blob/master/x-IMU%20IMU%20and%20AHRS%20Algorithms/x-IMU%20IMU%20and%20AHRS%20Algorithms/AHRS/MahonyAHRS.cs
|
||||
void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
||||
|
|
|
@ -23,6 +23,8 @@ public:
|
|||
static constexpr float GyroMaxValue = 5.0f;
|
||||
static constexpr float AccelMaxValue = 7.0f;
|
||||
|
||||
static constexpr std::size_t CalibrationSamples = 300;
|
||||
|
||||
explicit MotionInput();
|
||||
|
||||
MotionInput(const MotionInput&) = default;
|
||||
|
@ -49,6 +51,8 @@ public:
|
|||
void UpdateRotation(u64 elapsed_time);
|
||||
void UpdateOrientation(u64 elapsed_time);
|
||||
|
||||
void Calibrate();
|
||||
|
||||
[[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
|
||||
[[nodiscard]] Common::Vec3f GetAcceleration() const;
|
||||
[[nodiscard]] Common::Vec3f GetGyroscope() const;
|
||||
|
@ -61,6 +65,7 @@ public:
|
|||
[[nodiscard]] bool IsCalibrated(f32 sensitivity) const;
|
||||
|
||||
private:
|
||||
void StopCalibration();
|
||||
void ResetOrientation();
|
||||
void SetOrientationFromAccelerometer();
|
||||
|
||||
|
@ -103,6 +108,12 @@ private:
|
|||
|
||||
// Use accelerometer values to calculate position
|
||||
bool only_accelerometer = true;
|
||||
|
||||
// When enabled it will aggressively adjust for gyro drift
|
||||
bool calibration_mode = false;
|
||||
|
||||
// Used to auto disable calibration mode
|
||||
std::size_t calibration_counter = 0;
|
||||
};
|
||||
|
||||
} // namespace Core::HID
|
||||
|
|
|
@ -109,14 +109,37 @@ public:
|
|||
}
|
||||
|
||||
bool RumblePlay(const Common::Input::VibrationStatus vibration) {
|
||||
constexpr u32 rumble_max_duration_ms = 1000;
|
||||
constexpr u32 rumble_max_duration_ms = 2000;
|
||||
constexpr f32 low_start_sensitivity_limit = 140.0;
|
||||
constexpr f32 low_width_sensitivity_limit = 400.0;
|
||||
constexpr f32 high_start_sensitivity_limit = 200.0;
|
||||
constexpr f32 high_width_sensitivity_limit = 700.0;
|
||||
// Try to provide some feeling of the frequency by reducing the amplitude depending on it.
|
||||
f32 low_frequency_scale = 1.0;
|
||||
if (vibration.low_frequency > low_start_sensitivity_limit) {
|
||||
low_frequency_scale =
|
||||
std::max(1.0f - (vibration.low_frequency - low_start_sensitivity_limit) /
|
||||
low_width_sensitivity_limit,
|
||||
0.3f);
|
||||
}
|
||||
f32 low_amplitude = vibration.low_amplitude * low_frequency_scale;
|
||||
|
||||
f32 high_frequency_scale = 1.0;
|
||||
if (vibration.high_frequency > high_start_sensitivity_limit) {
|
||||
high_frequency_scale =
|
||||
std::max(1.0f - (vibration.high_frequency - high_start_sensitivity_limit) /
|
||||
high_width_sensitivity_limit,
|
||||
0.3f);
|
||||
}
|
||||
f32 high_amplitude = vibration.high_amplitude * high_frequency_scale;
|
||||
|
||||
if (sdl_controller) {
|
||||
return SDL_GameControllerRumble(
|
||||
sdl_controller.get(), static_cast<u16>(vibration.low_amplitude),
|
||||
static_cast<u16>(vibration.high_amplitude), rumble_max_duration_ms) != -1;
|
||||
return SDL_GameControllerRumble(sdl_controller.get(), static_cast<u16>(low_amplitude),
|
||||
static_cast<u16>(high_amplitude),
|
||||
rumble_max_duration_ms) != -1;
|
||||
} else if (sdl_joystick) {
|
||||
return SDL_JoystickRumble(sdl_joystick.get(), static_cast<u16>(vibration.low_amplitude),
|
||||
static_cast<u16>(vibration.high_amplitude),
|
||||
return SDL_JoystickRumble(sdl_joystick.get(), static_cast<u16>(low_amplitude),
|
||||
static_cast<u16>(high_amplitude),
|
||||
rumble_max_duration_ms) != -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1284,7 +1284,7 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu
|
|||
const VAddr overlap_cpu_addr = overlap.CpuAddr();
|
||||
const bool expands_left = overlap_cpu_addr < begin;
|
||||
if (expands_left) {
|
||||
cpu_addr = begin = overlap_cpu_addr;
|
||||
begin = overlap_cpu_addr;
|
||||
}
|
||||
const VAddr overlap_end = overlap_cpu_addr + overlap.SizeBytes();
|
||||
const bool expands_right = overlap_end > end;
|
||||
|
@ -1297,8 +1297,10 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu
|
|||
// as a stream buffer. Increase the size to skip constantly recreating buffers.
|
||||
has_stream_leap = true;
|
||||
if (expands_right) {
|
||||
begin -= CACHING_PAGESIZE * 256;
|
||||
cpu_addr = begin;
|
||||
begin -= YUZU_PAGESIZE * 256;
|
||||
// We're about to increment cpu_addr by YUZU_PAGESIZE, but have not yet checked for
|
||||
// a buffer at the new begin.
|
||||
cpu_addr = begin - YUZU_PAGESIZE;
|
||||
}
|
||||
if (expands_left) {
|
||||
end += CACHING_PAGESIZE * 256;
|
||||
|
@ -1321,7 +1323,7 @@ void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id,
|
|||
if (accumulate_stream_score) {
|
||||
new_buffer.IncreaseStreamScore(overlap.StreamScore() + 1);
|
||||
}
|
||||
boost::container::small_vector<BufferCopy, 1> copies;
|
||||
boost::container::small_vector<BufferCopy, 10> copies;
|
||||
const size_t dst_base_offset = overlap.CpuAddr() - new_buffer.CpuAddr();
|
||||
copies.push_back(BufferCopy{
|
||||
.src_offset = 0,
|
||||
|
|
|
@ -12,11 +12,11 @@ ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(const Core::System& system_
|
|||
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->enable_compute_pipelines_checkbox->setVisible(false);
|
||||
|
||||
SetupPerGameUI();
|
||||
|
||||
SetConfiguration();
|
||||
|
||||
ui->enable_compute_pipelines_checkbox->setVisible(false);
|
||||
}
|
||||
|
||||
ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default;
|
||||
|
|
|
@ -479,6 +479,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
param.Set("threshold", new_threshold / 1000.0f);
|
||||
emulated_controller->SetMotionParam(motion_id, param);
|
||||
});
|
||||
context_menu.addAction(tr("Calibrate sensor"), [&] {
|
||||
emulated_controller->StartMotionCalibration();
|
||||
});
|
||||
}
|
||||
context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location));
|
||||
});
|
||||
|
|
|
@ -582,9 +582,9 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
|
|||
using namespace Settings::NativeMotion;
|
||||
p.setPen(colors.outline);
|
||||
p.setBrush(colors.transparent);
|
||||
Draw3dCube(p, center + QPointF(-180, -5),
|
||||
Draw3dCube(p, center + QPointF(-180, 90),
|
||||
motion_values[Settings::NativeMotion::MotionLeft].euler, 20.0f);
|
||||
Draw3dCube(p, center + QPointF(180, -5),
|
||||
Draw3dCube(p, center + QPointF(180, 90),
|
||||
motion_values[Settings::NativeMotion::MotionRight].euler, 20.0f);
|
||||
}
|
||||
|
||||
|
@ -2926,14 +2926,14 @@ void PlayerControlPreview::DrawArrow(QPainter& p, const QPointF center, const Di
|
|||
void PlayerControlPreview::Draw3dCube(QPainter& p, QPointF center, const Common::Vec3f& euler,
|
||||
float size) {
|
||||
std::array<Common::Vec3f, 8> cube{
|
||||
Common::Vec3f{-1, -1, -1},
|
||||
{-1, 1, -1},
|
||||
{1, 1, -1},
|
||||
{1, -1, -1},
|
||||
{-1, -1, 1},
|
||||
{-1, 1, 1},
|
||||
{1, 1, 1},
|
||||
{1, -1, 1},
|
||||
Common::Vec3f{-0.7f, -1, -0.5f},
|
||||
{-0.7f, 1, -0.5f},
|
||||
{0.7f, 1, -0.5f},
|
||||
{0.7f, -1, -0.5f},
|
||||
{-0.7f, -1, 0.5f},
|
||||
{-0.7f, 1, 0.5f},
|
||||
{0.7f, 1, 0.5f},
|
||||
{0.7f, -1, 0.5f},
|
||||
};
|
||||
|
||||
for (Common::Vec3f& point : cube) {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/frontend/emu_window.h"
|
||||
#include "yuzu/qt_common.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#if !defined(WIN32) && !defined(__APPLE__)
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue