Files
rpcs3/rpcs3/Emu/Io/LogitechG27Config.cpp
T
Nico Franke 8d9abd396b Make FFB direction encoding for emulated G27 configurable (#18776)
This adds a dropdown in the emulated G27 settings dialog ("Force
feedback direction encoding") with three options: Steering Axis
(default), Cartesian, Polar. Default is Steering Axis so existing users
see no change.

RPCS3 right now hardcodes SDL_HAPTIC_STEERING_AXIS for the spring and
constant-force effects it sends to the host wheel. That's SDL's
recommended encoding for wheels and works on the hardware the code was
written against. Some Windows DirectInput drivers (like my MOZA R3) do
not react to these affects at all. This now allows changing it to an
encoding that works.
2026-06-05 20:09:35 +02:00

117 lines
2.3 KiB
C++

#include "stdafx.h"
#ifdef HAVE_SDL3
#include "Utilities/File.h"
#include "LogitechG27Config.h"
template <>
void fmt_class_string<sdl_mapping_type>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](sdl_mapping_type value)
{
switch (value)
{
case sdl_mapping_type::button: return "button";
case sdl_mapping_type::hat: return "hat";
case sdl_mapping_type::axis: return "axis";
}
return unknown;
});
}
template <>
void fmt_class_string<hat_component>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](hat_component value)
{
switch (value)
{
case hat_component::up: return "up";
case hat_component::down: return "down";
case hat_component::left: return "left";
case hat_component::right: return "right";
case hat_component::none: return "";
}
return unknown;
});
}
template <>
void fmt_class_string<g27_ffb_direction_type>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](g27_ffb_direction_type value)
{
switch (value)
{
case g27_ffb_direction_type::steering_axis: return "steering_axis";
case g27_ffb_direction_type::cartesian: return "cartesian";
case g27_ffb_direction_type::polar: return "polar";
}
return unknown;
});
}
emulated_logitech_g27_config g_cfg_logitech_g27;
LOG_CHANNEL(cfg_log, "CFG");
emulated_logitech_g27_config::emulated_logitech_g27_config()
: m_path(fs::get_config_dir(true) + "LogitechG27.yml")
{
}
void emulated_logitech_g27_config::reset()
{
const std::lock_guard lock(m_mutex);
cfg::node::from_default();
}
void emulated_logitech_g27_config::save(bool lock_mutex)
{
std::unique_lock lock(m_mutex, std::defer_lock);
if (lock_mutex)
{
lock.lock();
}
cfg_log.notice("Saving LogitechG27 config: '%s'", m_path);
if (!fs::create_path(fs::get_parent_dir(m_path)))
{
cfg_log.fatal("Failed to create path: '%s' (%s)", m_path, fs::g_tls_error);
}
if (!cfg::node::save(m_path))
{
cfg_log.error("Failed to save LogitechG27 config to '%s' (error=%s)", m_path, fs::g_tls_error);
}
}
bool emulated_logitech_g27_config::load()
{
const std::lock_guard lock(m_mutex);
cfg_log.notice("Loading LogitechG27 config: %s", m_path);
from_default();
if (fs::file cfg_file{m_path, fs::read})
{
if (const std::string content = cfg_file.to_string(); !content.empty())
{
return from_string(content);
}
}
else
{
save(false);
}
return true;
}
#endif