mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
dbd7c70ffd
36 changed files with 1465 additions and 965 deletions
|
@ -22,11 +22,8 @@ matrix:
|
|||
compiler: gcc
|
||||
|
||||
git:
|
||||
depth: false # Unshallow clone to obtain proper GIT_VERSION
|
||||
submodules: false
|
||||
# Unshallow clone to obtain proper GIT_VERSION
|
||||
# There's no variable to disable depth, so we just have to set it to a huge number
|
||||
# https://docs.travis-ci.com/user/customizing-the-build/#Git-Clone-Depth
|
||||
depth: 100000
|
||||
|
||||
before_install:
|
||||
- if [ "$CC" = "clang" ]; then
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include "recursive_wrapper.hpp"
|
||||
#include "variant_visitor.hpp"
|
||||
|
||||
// clang-format off
|
||||
// [[deprecated]] is only available in C++14, use this for the time being
|
||||
|
@ -849,6 +850,22 @@ namespace std {
|
|||
return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
|
||||
}
|
||||
|
||||
// match
|
||||
// unary
|
||||
template <typename... Fs>
|
||||
auto VARIANT_INLINE match(Fs&&... fs) const
|
||||
-> decltype(variant::visit(*this, ::std::make_visitor(std::forward<Fs>(fs)...)))
|
||||
{
|
||||
return variant::visit(*this, ::std::make_visitor(std::forward<Fs>(fs)...));
|
||||
}
|
||||
// non-const
|
||||
template <typename... Fs>
|
||||
auto VARIANT_INLINE match(Fs&&... fs)
|
||||
-> decltype(variant::visit(*this, ::std::make_visitor(std::forward<Fs>(fs)...)))
|
||||
{
|
||||
return variant::visit(*this, ::std::make_visitor(std::forward<Fs>(fs)...));
|
||||
}
|
||||
|
||||
~variant() noexcept // no-throw destructor
|
||||
{
|
||||
helper_type::destroy(type_index, &data);
|
||||
|
|
45
Utilities/variant_visitor.hpp
Normal file
45
Utilities/variant_visitor.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP
|
||||
#define MAPBOX_UTIL_VARIANT_VISITOR_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
//namespace mapbox {
|
||||
//namespace util {
|
||||
namespace std {
|
||||
|
||||
template <typename... Fns>
|
||||
struct visitor;
|
||||
|
||||
template <typename Fn>
|
||||
struct visitor<Fn> : Fn
|
||||
{
|
||||
using Fn::operator();
|
||||
|
||||
template<typename T>
|
||||
visitor(T&& fn) : Fn(std::forward<T>(fn)) {}
|
||||
};
|
||||
|
||||
template <typename Fn, typename... Fns>
|
||||
struct visitor<Fn, Fns...> : Fn, visitor<Fns...>
|
||||
{
|
||||
using Fn::operator();
|
||||
using visitor<Fns...>::operator();
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
visitor(T&& fn, Ts&&... fns)
|
||||
: Fn(std::forward<T>(fn))
|
||||
, visitor<Fns...>(std::forward<Ts>(fns)...) {}
|
||||
};
|
||||
|
||||
template <typename... Fns>
|
||||
visitor<typename std::decay<Fns>::type...> make_visitor(Fns&&... fns)
|
||||
{
|
||||
return visitor<typename std::decay<Fns>::type...>
|
||||
(std::forward<Fns>(fns)...);
|
||||
}
|
||||
|
||||
}
|
||||
//} // namespace util
|
||||
//} // namespace mapbox
|
||||
|
||||
#endif // MAPBOX_UTIL_VARIANT_VISITOR_HPP
|
|
@ -11,13 +11,14 @@ if(WIN32)
|
|||
find_package(Qt5 5.7 COMPONENTS WinExtras REQUIRED)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::WinExtras Qt5::Network)
|
||||
else()
|
||||
find_package(Qt5 5.7 COMPONENTS DBus)
|
||||
find_package(Qt5 5.7 COMPONENTS DBus Gui)
|
||||
if(Qt5DBus_FOUND)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::DBus Qt5::Network)
|
||||
add_definitions(-DHAVE_QTDBUS)
|
||||
else()
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::Network)
|
||||
endif()
|
||||
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# Let's make sure we have Qt before we continue
|
||||
|
@ -153,6 +154,11 @@ elseif(NOT MSVC AND NOT CMAKE_CXX_FLAGS MATCHES "LIBICONV_PLUG")
|
|||
endif()
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} "X11")
|
||||
find_package(Wayland)
|
||||
if (WAYLAND_FOUND)
|
||||
include_directories(${WAYLAND_INCLUDE_DIR})
|
||||
add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT RPCS3_SRC_DIR)
|
||||
|
|
|
@ -289,9 +289,14 @@ error_code cellGameUpdateCheckFinishAsync(ppu_thread& ppu, vm::ptr<CellGameUpdat
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsync(vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsync(ppu_thread& ppu, vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckStartWithoutDialogAsync(cb_func=*0x%x, userdata=*0x%x)", cb_func, userdata);
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, CELL_OK, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -301,21 +306,37 @@ error_code cellGameUpdateCheckAbort()
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckStartAsyncEx(vm::cptr<CellGameUpdateParam> param, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartAsyncEx(ppu_thread& ppu, vm::cptr<CellGameUpdateParam> param, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckStartAsyncEx(param=*0x%x, cb_func=*0x%x, userdata=*0x%x)", param, cb_func, userdata);
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, vm::make_var(CellGameUpdateResult{ CELL_OK, CELL_OK, 0x0, 0x0}), userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckFinishAsyncEx(vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckFinishAsyncEx(ppu_thread& ppu, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckFinishAsyncEx(cb_func=*0x%x, userdata=*0x%x)", cb_func, userdata);
|
||||
const s32 PROCESSING_COMPLETE = 5;
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, vm::make_var(CellGameUpdateResult{ PROCESSING_COMPLETE, CELL_OK, 0x0, 0x0}), userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsyncEx(vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsyncEx(ppu_thread& ppu, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckStartWithoutDialogAsyncEx(cb_func=*0x%x, userdata=*0x%x)", cb_func, userdata);
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, vm::make_var(CellGameUpdateResult{ CELL_OK, CELL_OK, 0x0, 0x0}), userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ extern const ppu_decoder<ppu_interpreter_fast> g_ppu_interpreter_fast([](auto& t
|
|||
|
||||
extern void ppu_initialize();
|
||||
extern void ppu_initialize(const ppu_module& info);
|
||||
static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name, u32 fragment_index, atomic_t<u32>&);
|
||||
static void ppu_initialize2(class jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name, u32 fragment_index, atomic_t<u32>&);
|
||||
extern void ppu_execute_syscall(ppu_thread& ppu, u64 code);
|
||||
|
||||
// Get pointer to executable cache
|
||||
|
|
|
@ -10,6 +10,10 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void init_config(pad_config* /*cfg*/, const std::string& /*name*/) override
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<std::string> ListDevices() override
|
||||
{
|
||||
std::vector<std::string> nulllist;
|
||||
|
@ -17,7 +21,7 @@ public:
|
|||
return nulllist;
|
||||
}
|
||||
|
||||
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override
|
||||
bool bindPadToDevice(std::shared_ptr<Pad> /*pad*/, const std::string& /*device*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -25,5 +29,4 @@ public:
|
|||
void ThreadProc() override
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
|
288
rpcs3/Emu/Io/PadHandler.cpp
Normal file
288
rpcs3/Emu/Io/PadHandler.cpp
Normal file
|
@ -0,0 +1,288 @@
|
|||
#include "stdafx.h"
|
||||
#include "PadHandler.h"
|
||||
|
||||
cfg_input g_cfg_input;
|
||||
|
||||
PadHandlerBase::PadHandlerBase(pad_handler type) : m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
// Search an unordered map for a string value and return found keycode
|
||||
int PadHandlerBase::FindKeyCode(std::unordered_map<u32, std::string> map, const cfg::string& name, bool fallback)
|
||||
{
|
||||
std::string def = name.def;
|
||||
std::string nam = name.to_string();
|
||||
int def_code = -1;
|
||||
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
if (it->second == nam)
|
||||
return it->first;
|
||||
|
||||
if (fallback && it->second == def)
|
||||
def_code = it->first;
|
||||
}
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
LOG_ERROR(HLE, "int FindKeyCode for [name = %s] returned with [def_code = %d] for [def = %s]", nam, def_code, def);
|
||||
if (def_code < 0)
|
||||
def_code = 0;
|
||||
}
|
||||
|
||||
return def_code;
|
||||
}
|
||||
|
||||
long PadHandlerBase::FindKeyCode(std::unordered_map<u64, std::string> map, const cfg::string& name, bool fallback)
|
||||
{
|
||||
std::string def = name.def;
|
||||
std::string nam = name.to_string();
|
||||
long def_code = -1;
|
||||
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
if (it->second == nam)
|
||||
return static_cast<long>(it->first);
|
||||
|
||||
if (fallback && it->second == def)
|
||||
def_code = static_cast<long>(it->first);
|
||||
}
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
LOG_ERROR(HLE, "long FindKeyCode for [name = %s] returned with [def_code = %d] for [def = %s]", nam, def_code, def);
|
||||
if (def_code < 0)
|
||||
def_code = 0;
|
||||
}
|
||||
|
||||
return def_code;
|
||||
}
|
||||
|
||||
// Search an unordered map for a string value and return found keycode
|
||||
int PadHandlerBase::FindKeyCodeByString(std::unordered_map<u32, std::string> map, const std::string& name, bool fallback)
|
||||
{
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
if (it->second == name)
|
||||
return it->first;
|
||||
}
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
LOG_ERROR(HLE, "long FindKeyCodeByString fohr [name = %s] returned with 0", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Search an unordered map for a string value and return found keycode
|
||||
long PadHandlerBase::FindKeyCodeByString(std::unordered_map<u64, std::string> map, const std::string& name, bool fallback)
|
||||
{
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
if (it->second == name)
|
||||
return static_cast<long>(it->first);
|
||||
}
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
LOG_ERROR(HLE, "long FindKeyCodeByString fohr [name = %s] returned with 0", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get new scaled value between 0 and 255 based on its minimum and maximum
|
||||
float PadHandlerBase::ScaleStickInput(s32 raw_value, int minimum, int maximum)
|
||||
{
|
||||
// value based on max range converted to [0, 1]
|
||||
float val = float(Clamp(static_cast<f32>(raw_value), minimum, maximum) - minimum) / float(abs(maximum) + abs(minimum));
|
||||
return 255.0f * val;
|
||||
}
|
||||
|
||||
// Get new scaled value between -255 and 255 based on its minimum and maximum
|
||||
float PadHandlerBase::ScaleStickInput2(s32 raw_value, int minimum, int maximum)
|
||||
{
|
||||
// value based on max range converted to [0, 1]
|
||||
float val = float(Clamp(static_cast<f32>(raw_value), minimum, maximum) - minimum) / float(abs(maximum) + abs(minimum));
|
||||
return (510.0f * val) - 255.0f;
|
||||
}
|
||||
|
||||
// Get normalized trigger value based on the range defined by a threshold
|
||||
u16 PadHandlerBase::NormalizeTriggerInput(u16 value, int threshold)
|
||||
{
|
||||
if (value <= threshold || threshold >= trigger_max)
|
||||
{
|
||||
return static_cast<u16>(0);
|
||||
}
|
||||
else if (threshold <= trigger_min)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (u16)(float(trigger_max) * float(value - threshold) / float(trigger_max - threshold));
|
||||
}
|
||||
}
|
||||
|
||||
// normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions
|
||||
// the input values must lie in 0+
|
||||
u16 PadHandlerBase::NormalizeDirectedInput(u16 raw_value, s32 threshold, s32 maximum)
|
||||
{
|
||||
if (threshold >= maximum || maximum <= 0)
|
||||
{
|
||||
return static_cast<u16>(0);
|
||||
}
|
||||
|
||||
float val = float(Clamp(raw_value, 0, maximum)) / float(maximum); // value based on max range converted to [0, 1]
|
||||
|
||||
if (threshold <= 0)
|
||||
{
|
||||
return static_cast<u16>(255.0f * val);
|
||||
}
|
||||
else
|
||||
{
|
||||
float thresh = float(threshold) / float(maximum); // threshold converted to [0, 1]
|
||||
return static_cast<u16>(255.0f * std::min(1.0f, (val - thresh) / (1.0f - thresh)));
|
||||
}
|
||||
}
|
||||
|
||||
u16 PadHandlerBase::NormalizeStickInput(u16 raw_value, int threshold, bool ignore_threshold)
|
||||
{
|
||||
if (ignore_threshold)
|
||||
{
|
||||
return static_cast<u16>(ScaleStickInput(raw_value, 0, thumb_max));
|
||||
}
|
||||
else
|
||||
{
|
||||
return NormalizeDirectedInput(raw_value, threshold, thumb_max);
|
||||
}
|
||||
}
|
||||
|
||||
// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13%
|
||||
// X and Y is expected to be in (-255) to 255 range, deadzone should be in terms of thumb stick range
|
||||
// return is new x and y values in 0-255 range
|
||||
std::tuple<u16, u16> PadHandlerBase::NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone)
|
||||
{
|
||||
const float dzRange = deadzone / float((std::abs(thumb_max) + std::abs(thumb_min)));
|
||||
|
||||
float X = inX / 255.0f;
|
||||
float Y = inY / 255.0f;
|
||||
|
||||
if (dzRange > 0.f)
|
||||
{
|
||||
const float mag = std::min(sqrtf(X*X + Y*Y), 1.f);
|
||||
|
||||
if (mag <= 0)
|
||||
{
|
||||
return std::tuple<u16, u16>(ConvertAxis(X), ConvertAxis(Y));
|
||||
}
|
||||
|
||||
if (mag > dzRange) {
|
||||
float pos = lerp(0.13f, 1.f, (mag - dzRange) / (1 - dzRange));
|
||||
float scale = pos / mag;
|
||||
X = X * scale;
|
||||
Y = Y * scale;
|
||||
}
|
||||
else {
|
||||
float pos = lerp(0.f, 0.13f, mag / dzRange);
|
||||
float scale = pos / mag;
|
||||
X = X * scale;
|
||||
Y = Y * scale;
|
||||
}
|
||||
}
|
||||
return std::tuple<u16, u16>(ConvertAxis(X), ConvertAxis(Y));
|
||||
}
|
||||
|
||||
// get clamped value between min and max
|
||||
s32 PadHandlerBase::Clamp(f32 input, s32 min, s32 max)
|
||||
{
|
||||
if (input > max)
|
||||
return max;
|
||||
else if (input < min)
|
||||
return min;
|
||||
else return static_cast<s32>(input);
|
||||
}
|
||||
|
||||
// get clamped value between 0 and 255
|
||||
u16 PadHandlerBase::Clamp0To255(f32 input)
|
||||
{
|
||||
return static_cast<u16>(Clamp(input, 0, 255));
|
||||
}
|
||||
|
||||
// get clamped value between 0 and 1023
|
||||
u16 PadHandlerBase::Clamp0To1023(f32 input)
|
||||
{
|
||||
return static_cast<u16>(Clamp(input, 0, 1023));
|
||||
}
|
||||
|
||||
// input has to be [-1,1]. result will be [0,255]
|
||||
u16 PadHandlerBase::ConvertAxis(float value)
|
||||
{
|
||||
return static_cast<u16>((value + 1.0)*(255.0 / 2.0));
|
||||
}
|
||||
|
||||
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
|
||||
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
|
||||
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000
|
||||
// This function assumes inX and inY is already in 0-255
|
||||
std::tuple<u16, u16> PadHandlerBase::ConvertToSquirclePoint(u16 inX, u16 inY, int squircle_factor)
|
||||
{
|
||||
// convert inX and Y to a (-1, 1) vector;
|
||||
const f32 x = ((f32)inX - 127.5f) / 127.5f;
|
||||
const f32 y = ((f32)inY - 127.5f) / 127.5f;
|
||||
|
||||
// compute angle and len of given point to be used for squircle radius
|
||||
const f32 angle = std::atan2(y, x);
|
||||
const f32 r = std::sqrt(std::pow(x, 2.f) + std::pow(y, 2.f));
|
||||
|
||||
// now find len/point on the given squircle from our current angle and radius in polar coords
|
||||
// https://thatsmaths.com/2016/07/14/squircles/
|
||||
const f32 newLen = (1 + std::pow(std::sin(2 * angle), 2.f) / (float(squircle_factor) / 1000.f)) * r;
|
||||
|
||||
// we now have len and angle, convert to cartisian
|
||||
const int newX = Clamp0To255(((newLen * std::cos(angle)) + 1) * 127.5f);
|
||||
const int newY = Clamp0To255(((newLen * std::sin(angle)) + 1) * 127.5f);
|
||||
return std::tuple<u16, u16>(newX, newY);
|
||||
}
|
||||
|
||||
bool PadHandlerBase::has_config()
|
||||
{
|
||||
return b_has_config;
|
||||
}
|
||||
|
||||
bool PadHandlerBase::has_rumble()
|
||||
{
|
||||
return b_has_rumble;
|
||||
}
|
||||
|
||||
bool PadHandlerBase::has_deadzones()
|
||||
{
|
||||
return b_has_deadzones;
|
||||
}
|
||||
|
||||
std::string PadHandlerBase::get_config_dir(pad_handler type)
|
||||
{
|
||||
return fs::get_config_dir() + "/InputConfigs/" + fmt::format("%s", type) + "/";
|
||||
}
|
||||
|
||||
std::string PadHandlerBase::get_config_filename(int i)
|
||||
{
|
||||
return fs::get_config_dir() + "/InputConfigs/" + g_cfg_input.player[i]->handler.to_string() + "/" + g_cfg_input.player[i]->profile.to_string() + ".yml";
|
||||
}
|
||||
|
||||
void PadHandlerBase::init_configs()
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
if (g_cfg_input.player[i]->handler == m_type)
|
||||
{
|
||||
init_config(&m_pad_configs[index], get_config_filename(i));
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "../../Utilities/Config.h"
|
||||
#include "../../Utilities/types.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
// TODO: HLE info (constants, structs, etc.) should not be available here
|
||||
|
||||
|
@ -248,9 +249,50 @@ struct Pad
|
|||
}
|
||||
};
|
||||
|
||||
struct pad_config : cfg::node
|
||||
struct cfg_player final : cfg::node
|
||||
{
|
||||
pad_handler def_handler = pad_handler::null;
|
||||
cfg_player(node* owner, const std::string& name, pad_handler type) : cfg::node(owner, name), def_handler(type) {};
|
||||
|
||||
cfg::_enum<pad_handler> handler{ this, "Handler", def_handler };
|
||||
cfg::string device{ this, "Device", handler.to_string() };
|
||||
cfg::string profile{ this, "Profile", "Default Profile" };
|
||||
};
|
||||
|
||||
struct cfg_input final : cfg::node
|
||||
{
|
||||
const std::string cfg_name = fs::get_config_dir() + "/config_input.yml";
|
||||
|
||||
cfg_player player1{ this, "Player 1 Input", pad_handler::keyboard };
|
||||
cfg_player player2{ this, "Player 2 Input", pad_handler::null };
|
||||
cfg_player player3{ this, "Player 3 Input", pad_handler::null };
|
||||
cfg_player player4{ this, "Player 4 Input", pad_handler::null };
|
||||
cfg_player player5{ this, "Player 5 Input", pad_handler::null };
|
||||
cfg_player player6{ this, "Player 6 Input", pad_handler::null };
|
||||
cfg_player player7{ this, "Player 7 Input", pad_handler::null };
|
||||
|
||||
cfg_player *player[7]{ &player1, &player2, &player3, &player4, &player5, &player6, &player7 }; // Thanks gcc!
|
||||
|
||||
bool load()
|
||||
{
|
||||
if (fs::file cfg_file{ cfg_name, fs::read })
|
||||
{
|
||||
return from_string(cfg_file.to_string());
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
void save()
|
||||
{
|
||||
fs::file(cfg_name, fs::rewrite).write(to_string());
|
||||
};
|
||||
};
|
||||
|
||||
extern cfg_input g_cfg_input;
|
||||
|
||||
struct pad_config final : cfg::node
|
||||
{
|
||||
std::string cfg_type = "";
|
||||
std::string cfg_name = "";
|
||||
|
||||
cfg::string ls_left { this, "Left Stick Left", "" };
|
||||
|
@ -327,7 +369,7 @@ protected:
|
|||
bool b_has_deadzones = false;
|
||||
bool b_has_rumble = false;
|
||||
bool b_has_config = false;
|
||||
pad_config m_pad_config;
|
||||
std::array<pad_config, MAX_GAMEPADS> m_pad_configs;
|
||||
|
||||
template <typename T>
|
||||
T lerp(T v0, T v1, T t) {
|
||||
|
@ -335,245 +377,52 @@ protected:
|
|||
}
|
||||
|
||||
// Search an unordered map for a string value and return found keycode
|
||||
int FindKeyCode(std::unordered_map<u32, std::string> map, const cfg::string& name, bool fallback = true)
|
||||
{
|
||||
std::string def = name.def;
|
||||
std::string nam = name.to_string();
|
||||
int def_code = -1;
|
||||
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
if (it->second == nam)
|
||||
return it->first;
|
||||
|
||||
if (fallback && it->second == def)
|
||||
def_code = it->first;
|
||||
}
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
LOG_ERROR(HLE, "int FindKeyCode for [name = %s] returned with [def_code = %d] for [def = %s]", nam, def_code, def);
|
||||
if (def_code < 0)
|
||||
def_code = 0;
|
||||
}
|
||||
|
||||
return def_code;
|
||||
};
|
||||
|
||||
long FindKeyCode(std::unordered_map<u64, std::string> map, const cfg::string& name, bool fallback = true)
|
||||
{
|
||||
std::string def = name.def;
|
||||
std::string nam = name.to_string();
|
||||
int def_code = -1;
|
||||
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
if (it->second == nam)
|
||||
return it->first;
|
||||
|
||||
if (fallback && it->second == def)
|
||||
def_code = it->first;
|
||||
}
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
LOG_ERROR(HLE, "long FindKeyCode for [name = %s] returned with [def_code = %d] for [def = %s]", nam, def_code, def);
|
||||
if (def_code < 0)
|
||||
def_code = 0;
|
||||
}
|
||||
|
||||
return def_code;
|
||||
};
|
||||
int FindKeyCode(std::unordered_map<u32, std::string> map, const cfg::string& name, bool fallback = true);
|
||||
|
||||
// Search an unordered map for a string value and return found keycode
|
||||
int FindKeyCodeByString(std::unordered_map<u32, std::string> map, const std::string& name, bool fallback = true)
|
||||
{
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
if (it->second == name)
|
||||
return it->first;
|
||||
}
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
LOG_ERROR(HLE, "long FindKeyCodeByString fohr [name = %s] returned with 0", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
long FindKeyCode(std::unordered_map<u64, std::string> map, const cfg::string& name, bool fallback = true);
|
||||
|
||||
// Search an unordered map for a string value and return found keycode
|
||||
long FindKeyCodeByString(std::unordered_map<u64, std::string> map, const std::string& name, bool fallback = true)
|
||||
{
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
if (it->second == name)
|
||||
return it->first;
|
||||
}
|
||||
int FindKeyCodeByString(std::unordered_map<u32, std::string> map, const std::string& name, bool fallback = true);
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
LOG_ERROR(HLE, "long FindKeyCodeByString fohr [name = %s] returned with 0", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Get normalized trigger value based on the range defined by a threshold
|
||||
u16 NormalizeTriggerInput(u16 value, int threshold)
|
||||
{
|
||||
if (value <= threshold || threshold >= trigger_max)
|
||||
{
|
||||
return static_cast<u16>(0);
|
||||
}
|
||||
else if (threshold <= trigger_min)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (u16)(float(trigger_max) * float(value - threshold) / float(trigger_max - threshold));
|
||||
}
|
||||
};
|
||||
// Search an unordered map for a string value and return found keycode
|
||||
long FindKeyCodeByString(std::unordered_map<u64, std::string> map, const std::string& name, bool fallback = true);
|
||||
|
||||
// Get new scaled value between 0 and 255 based on its minimum and maximum
|
||||
float ScaleStickInput(s32 raw_value, int minimum, int maximum)
|
||||
{
|
||||
// value based on max range converted to [0, 1]
|
||||
float val = float(Clamp(raw_value, minimum, maximum) - minimum) / float(abs(maximum) + abs(minimum));
|
||||
return 255.0f * val;
|
||||
};
|
||||
float ScaleStickInput(s32 raw_value, int minimum, int maximum);
|
||||
|
||||
// Get new scaled value between -255 and 255 based on its minimum and maximum
|
||||
float ScaleStickInput2(s32 raw_value, int minimum, int maximum)
|
||||
{
|
||||
// value based on max range converted to [0, 1]
|
||||
float val = float(Clamp(raw_value, minimum, maximum) - minimum) / float(abs(maximum) + abs(minimum));
|
||||
return (510.0f * val) - 255.0f;
|
||||
};
|
||||
float ScaleStickInput2(s32 raw_value, int minimum, int maximum);
|
||||
|
||||
// Get normalized trigger value based on the range defined by a threshold
|
||||
u16 NormalizeTriggerInput(u16 value, int threshold);
|
||||
|
||||
// normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions
|
||||
// the input values must lie in 0+
|
||||
u16 NormalizeDirectedInput(u16 raw_value, float threshold, float maximum)
|
||||
{
|
||||
if (threshold >= maximum || maximum <= 0)
|
||||
{
|
||||
return static_cast<u16>(0);
|
||||
}
|
||||
u16 NormalizeDirectedInput(u16 raw_value, s32 threshold, s32 maximum);
|
||||
|
||||
float val = float(Clamp(raw_value, 0, maximum)) / maximum; // value based on max range converted to [0, 1]
|
||||
|
||||
if (threshold <= 0)
|
||||
{
|
||||
return static_cast<u16>(255.0f * val);
|
||||
}
|
||||
else
|
||||
{
|
||||
float thresh = threshold / maximum; // threshold converted to [0, 1]
|
||||
return static_cast<u16>(255.0f * std::min(1.0f, (val - thresh) / (1.0f - thresh)));
|
||||
}
|
||||
};
|
||||
|
||||
u16 NormalizeStickInput(s32 raw_value, int threshold, bool ignore_threshold = false)
|
||||
{
|
||||
if (ignore_threshold)
|
||||
{
|
||||
return static_cast<u16>(ScaleStickInput(raw_value, 0, thumb_max));
|
||||
}
|
||||
else
|
||||
{
|
||||
return NormalizeDirectedInput(raw_value, threshold, thumb_max);
|
||||
}
|
||||
}
|
||||
u16 NormalizeStickInput(u16 raw_value, int threshold, bool ignore_threshold = false);
|
||||
|
||||
// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13%
|
||||
// X and Y is expected to be in (-255) to 255 range, deadzone should be in terms of thumb stick range
|
||||
// return is new x and y values in 0-255 range
|
||||
std::tuple<u16, u16> NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone)
|
||||
{
|
||||
const float dzRange = deadzone / float((std::abs(thumb_max) + std::abs(thumb_min)));
|
||||
|
||||
float X = inX / 255.0f;
|
||||
float Y = inY / 255.0f;
|
||||
|
||||
if (dzRange > 0.f)
|
||||
{
|
||||
const float mag = std::min(sqrtf(X*X + Y*Y), 1.f);
|
||||
|
||||
if (mag <= 0)
|
||||
{
|
||||
return std::tuple<u16, u16>(ConvertAxis(X), ConvertAxis(Y));
|
||||
}
|
||||
|
||||
if (mag > dzRange) {
|
||||
float pos = lerp(0.13f, 1.f, (mag - dzRange) / (1 - dzRange));
|
||||
float scale = pos / mag;
|
||||
X = X * scale;
|
||||
Y = Y * scale;
|
||||
}
|
||||
else {
|
||||
float pos = lerp(0.f, 0.13f, mag / dzRange);
|
||||
float scale = pos / mag;
|
||||
X = X * scale;
|
||||
Y = Y * scale;
|
||||
}
|
||||
}
|
||||
return std::tuple<u16, u16>( ConvertAxis(X), ConvertAxis(Y) );
|
||||
};
|
||||
std::tuple<u16, u16> NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone);
|
||||
|
||||
// get clamped value between min and max
|
||||
s32 Clamp(f32 input, s32 min, s32 max)
|
||||
{
|
||||
if (input > max)
|
||||
return max;
|
||||
else if (input < min)
|
||||
return min;
|
||||
else return static_cast<s32>(input);
|
||||
};
|
||||
|
||||
s32 Clamp(f32 input, s32 min, s32 max);
|
||||
// get clamped value between 0 and 255
|
||||
u16 Clamp0To255(f32 input)
|
||||
{
|
||||
return static_cast<u16>(Clamp(input, 0, 255));
|
||||
};
|
||||
|
||||
u16 Clamp0To255(f32 input);
|
||||
// get clamped value between 0 and 1023
|
||||
u16 Clamp0To1023(f32 input)
|
||||
{
|
||||
return static_cast<u16>(Clamp(input, 0, 1023));
|
||||
}
|
||||
u16 Clamp0To1023(f32 input);
|
||||
|
||||
// input has to be [-1,1]. result will be [0,255]
|
||||
u16 ConvertAxis(float value)
|
||||
{
|
||||
return static_cast<u16>((value + 1.0)*(255.0 / 2.0));
|
||||
};
|
||||
u16 ConvertAxis(float value);
|
||||
|
||||
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
|
||||
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
|
||||
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000
|
||||
// This function assumes inX and inY is already in 0-255
|
||||
std::tuple<u16, u16> ConvertToSquirclePoint(u16 inX, u16 inY, float squircle_factor)
|
||||
{
|
||||
// convert inX and Y to a (-1, 1) vector;
|
||||
const f32 x = ((f32)inX - 127.5f) / 127.5f;
|
||||
const f32 y = ((f32)inY - 127.5f) / 127.5f;
|
||||
|
||||
// compute angle and len of given point to be used for squircle radius
|
||||
const f32 angle = std::atan2(y, x);
|
||||
const f32 r = std::sqrt(std::pow(x, 2.f) + std::pow(y, 2.f));
|
||||
|
||||
// now find len/point on the given squircle from our current angle and radius in polar coords
|
||||
// https://thatsmaths.com/2016/07/14/squircles/
|
||||
const f32 newLen = (1 + std::pow(std::sin(2 * angle), 2.f) / (squircle_factor / 1000.f)) * r;
|
||||
|
||||
// we now have len and angle, convert to cartisian
|
||||
const int newX = Clamp0To255(((newLen * std::cos(angle)) + 1) * 127.5f);
|
||||
const int newY = Clamp0To255(((newLen * std::sin(angle)) + 1) * 127.5f);
|
||||
return std::tuple<u16, u16>(newX, newY);
|
||||
}
|
||||
// This function assumes inX and inY is already in 0-255
|
||||
std::tuple<u16, u16> ConvertToSquirclePoint(u16 inX, u16 inY, int squircle_factor);
|
||||
|
||||
public:
|
||||
s32 thumb_min = 0;
|
||||
|
@ -584,24 +433,32 @@ public:
|
|||
s32 vibration_max = 255;
|
||||
u32 connected = 0;
|
||||
|
||||
virtual bool Init() { return true; };
|
||||
virtual ~PadHandlerBase() = default;
|
||||
pad_handler m_type = pad_handler::null;
|
||||
|
||||
//Does it have GUI Config?
|
||||
bool has_config() { return b_has_config; };
|
||||
bool has_rumble() { return b_has_rumble; };
|
||||
bool has_deadzones() { return b_has_deadzones; };
|
||||
pad_config* GetConfig() { return &m_pad_config; };
|
||||
bool has_config();
|
||||
bool has_rumble();
|
||||
bool has_deadzones();
|
||||
|
||||
static std::string get_config_dir(pad_handler type);
|
||||
static std::string get_config_filename(int i);
|
||||
|
||||
virtual bool Init() { return true; };
|
||||
PadHandlerBase(pad_handler type = pad_handler::null);
|
||||
virtual ~PadHandlerBase() = default;
|
||||
//Sets window to config the controller(optional)
|
||||
virtual void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false, std::vector<std::string> buttons = {}) {};
|
||||
virtual void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) {};
|
||||
virtual void GetNextButtonPress(const std::string& /*padId*/, const std::function<void(u16, std::string, int[])>& /*callback*/, bool /*get_blacklist*/ = false, std::vector<std::string> /*buttons*/ = {}) {};
|
||||
virtual void TestVibration(const std::string& /*padId*/, u32 /*largeMotor*/, u32 /*smallMotor*/) {};
|
||||
//Return list of devices for that handler
|
||||
virtual std::vector<std::string> ListDevices() = 0;
|
||||
//Callback called during pad_thread::ThreadFunc
|
||||
virtual void ThreadProc() = 0;
|
||||
//Binds a Pad to a device
|
||||
virtual bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) = 0;
|
||||
virtual bool bindPadToDevice(std::shared_ptr<Pad> /*pad*/, const std::string& /*device*/) = 0;
|
||||
virtual void init_config(pad_config* /*cfg*/, const std::string& /*name*/) = 0;
|
||||
|
||||
private:
|
||||
virtual void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) {};
|
||||
virtual void TranslateButtonPress(u64 /*keyCode*/, bool& /*pressed*/, u16& /*val*/, bool /*ignore_threshold*/ = false) {};
|
||||
|
||||
protected:
|
||||
void init_configs();
|
||||
};
|
||||
|
|
|
@ -3,6 +3,19 @@
|
|||
#include "Emu/RSX/RSXThread.h"
|
||||
#include <memory>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
// Cannot include Xlib.h before Qt5
|
||||
// and we don't need all of Xlib anyway
|
||||
typedef struct _XDisplay Display;
|
||||
typedef unsigned long Window;
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include <wayland-client.h>
|
||||
#endif
|
||||
|
||||
struct RSXDebuggerProgram
|
||||
{
|
||||
u32 id;
|
||||
|
@ -34,6 +47,17 @@ using RSXDebuggerPrograms = std::vector<RSXDebuggerProgram>;
|
|||
|
||||
using draw_context_t = void*;
|
||||
|
||||
#ifdef _WIN32
|
||||
using display_handle_t = HWND;
|
||||
#else
|
||||
using display_handle_t = std::variant<
|
||||
std::pair<Display*, Window>
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
, std::pair<wl_display*, wl_surface*>
|
||||
#endif
|
||||
>;
|
||||
#endif
|
||||
|
||||
class GSFrameBase
|
||||
{
|
||||
public:
|
||||
|
@ -52,7 +76,7 @@ public:
|
|||
virtual int client_width() = 0;
|
||||
virtual int client_height() = 0;
|
||||
|
||||
virtual void* handle() const = 0;
|
||||
virtual display_handle_t handle() const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -494,12 +494,8 @@ VKGSRender::VKGSRender() : GSRender()
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
HINSTANCE hInstance = NULL;
|
||||
HWND hWnd = (HWND)m_frame->handle();
|
||||
std::vector<vk::physical_device>& gpus = m_thread_context.enumerateDevices();
|
||||
|
||||
std::vector<vk::physical_device>& gpus = m_thread_context.enumerateDevices();
|
||||
|
||||
//Actually confirm that the loader found at least one compatible device
|
||||
//This should not happen unless something is wrong with the driver setup on the target system
|
||||
if (gpus.size() == 0)
|
||||
|
@ -512,11 +508,18 @@ VKGSRender::VKGSRender() : GSRender()
|
|||
|
||||
bool gpu_found = false;
|
||||
std::string adapter_name = g_cfg.video.vk.adapter;
|
||||
|
||||
display_handle_t display = m_frame->handle();
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
HINSTANCE hInstance = NULL;
|
||||
|
||||
for (auto &gpu : gpus)
|
||||
{
|
||||
if (gpu.name() == adapter_name)
|
||||
{
|
||||
m_swap_chain = m_thread_context.createSwapChain(hInstance, hWnd, gpu);
|
||||
m_swap_chain = m_thread_context.createSwapChain(hInstance, display, gpu);
|
||||
gpu_found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -524,35 +527,18 @@ VKGSRender::VKGSRender() : GSRender()
|
|||
|
||||
if (!gpu_found || adapter_name.empty())
|
||||
{
|
||||
m_swap_chain = m_thread_context.createSwapChain(hInstance, hWnd, gpus[0]);
|
||||
m_swap_chain = m_thread_context.createSwapChain(hInstance, display, gpus[0]);
|
||||
}
|
||||
|
||||
|
||||
#elif HAVE_VULKAN
|
||||
|
||||
Window window = (Window)m_frame->handle();
|
||||
Display *display = XOpenDisplay(0);
|
||||
display.match([](std::pair<Display*, Window> p) { XFlush(p.first); }, [](auto _) {});
|
||||
|
||||
std::vector<vk::physical_device>& gpus = m_thread_context.enumerateDevices();
|
||||
|
||||
//Actually confirm that the loader found at least one compatible device
|
||||
//This should not happen unless something is wrong with the driver setup on the target system
|
||||
if (gpus.size() == 0)
|
||||
{
|
||||
//We can't throw in Emulator::Load, so we show error and return
|
||||
LOG_FATAL(RSX, "No compatible GPU devices found");
|
||||
m_device = VK_NULL_HANDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
XFlush(display);
|
||||
|
||||
bool gpu_found = false;
|
||||
std::string adapter_name = g_cfg.video.vk.adapter;
|
||||
for (auto &gpu : gpus)
|
||||
{
|
||||
if (gpu.name() == adapter_name)
|
||||
{
|
||||
m_swap_chain = m_thread_context.createSwapChain(display, window, gpu);
|
||||
m_swap_chain = m_thread_context.createSwapChain(display, gpu);
|
||||
gpu_found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -560,10 +546,10 @@ VKGSRender::VKGSRender() : GSRender()
|
|||
|
||||
if (!gpu_found || adapter_name.empty())
|
||||
{
|
||||
m_swap_chain = m_thread_context.createSwapChain(display, window, gpus[0]);
|
||||
m_swap_chain = m_thread_context.createSwapChain(display, gpus[0]);
|
||||
}
|
||||
|
||||
m_display_handle = display;
|
||||
|
||||
display.match([&](std::pair<Display*, Window> p) { m_display_handle = p.first; }, [](auto _) {});
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -8,10 +8,8 @@
|
|||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#include "Utilities/variant.hpp"
|
||||
#include "Emu/RSX/GSRender.h"
|
||||
#include "Emu/System.h"
|
||||
#include "VulkanAPI.h"
|
||||
#include "../GCM.h"
|
||||
|
@ -199,7 +197,7 @@ namespace vk
|
|||
//Set up instance information
|
||||
const char *requested_extensions[] =
|
||||
{
|
||||
"VK_KHR_swapchain"
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
||||
};
|
||||
|
||||
std::vector<const char *> layers;
|
||||
|
@ -324,7 +322,7 @@ namespace vk
|
|||
VkDevice dev = (VkDevice)(*owner);
|
||||
|
||||
u32 access_mask = 0;
|
||||
|
||||
|
||||
if (host_visible)
|
||||
access_mask |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||
|
||||
|
@ -412,7 +410,7 @@ namespace vk
|
|||
|
||||
VkMemoryRequirements memory_req;
|
||||
vkGetImageMemoryRequirements(m_device, value, &memory_req);
|
||||
|
||||
|
||||
if (!(memory_req.memoryTypeBits & (1 << memory_type_index)))
|
||||
{
|
||||
//Suggested memory type is incompatible with this memory type.
|
||||
|
@ -953,7 +951,7 @@ namespace vk
|
|||
|
||||
nb_swap_images = 0;
|
||||
getSwapchainImagesKHR(dev, m_vk_swapchain, &nb_swap_images, nullptr);
|
||||
|
||||
|
||||
if (!nb_swap_images) fmt::throw_exception("Driver returned 0 images for swapchain" HERE);
|
||||
|
||||
std::vector<VkImage> swap_images;
|
||||
|
@ -1185,11 +1183,11 @@ namespace vk
|
|||
m_instance = nullptr;
|
||||
m_vk_instances.resize(0);
|
||||
}
|
||||
|
||||
|
||||
void enable_debugging()
|
||||
{
|
||||
if (!g_cfg.video.debug_output) return;
|
||||
|
||||
|
||||
PFN_vkDebugReportCallbackEXT callback = vk::dbgFunc;
|
||||
|
||||
createDebugReportCallback = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(m_instance, "vkCreateDebugReportCallbackEXT");
|
||||
|
@ -1220,13 +1218,16 @@ namespace vk
|
|||
//Set up instance information
|
||||
const char *requested_extensions[] =
|
||||
{
|
||||
"VK_KHR_surface",
|
||||
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||
#ifdef _WIN32
|
||||
"VK_KHR_win32_surface",
|
||||
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
|
||||
#else
|
||||
"VK_KHR_xlib_surface",
|
||||
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
|
||||
#endif
|
||||
"VK_EXT_debug_report",
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
|
||||
#endif
|
||||
VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
std::vector<const char *> layers;
|
||||
|
@ -1239,7 +1240,7 @@ namespace vk
|
|||
instance_info.pApplicationInfo = &app;
|
||||
instance_info.enabledLayerCount = static_cast<uint32_t>(layers.size());
|
||||
instance_info.ppEnabledLayerNames = layers.data();
|
||||
instance_info.enabledExtensionCount = fast? 0: 3;
|
||||
instance_info.enabledExtensionCount = fast? 0: sizeof(requested_extensions)/sizeof(char*);
|
||||
instance_info.ppEnabledExtensionNames = fast? nullptr: requested_extensions;
|
||||
|
||||
VkInstance instance;
|
||||
|
@ -1304,8 +1305,8 @@ namespace vk
|
|||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
vk::swap_chain* createSwapChain(HINSTANCE hInstance, HWND hWnd, vk::physical_device &dev)
|
||||
|
||||
vk::swap_chain* createSwapChain(HINSTANCE hInstance, display_handle_t hWnd, vk::physical_device &dev)
|
||||
{
|
||||
VkWin32SurfaceCreateInfoKHR createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||
|
@ -1315,16 +1316,31 @@ namespace vk
|
|||
VkSurfaceKHR surface;
|
||||
CHECK_RESULT(vkCreateWin32SurfaceKHR(m_instance, &createInfo, NULL, &surface));
|
||||
#elif HAVE_VULKAN
|
||||
|
||||
vk::swap_chain* createSwapChain(Display *display, Window window, vk::physical_device &dev)
|
||||
|
||||
vk::swap_chain* createSwapChain(display_handle_t ctx, vk::physical_device &dev)
|
||||
{
|
||||
VkXlibSurfaceCreateInfoKHR createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.dpy = display;
|
||||
createInfo.window = window;
|
||||
|
||||
VkSurfaceKHR surface;
|
||||
CHECK_RESULT(vkCreateXlibSurfaceKHR(m_instance, &createInfo, nullptr, &surface));
|
||||
|
||||
ctx.match(
|
||||
[&](std::pair<Display*, Window> p)
|
||||
{
|
||||
VkXlibSurfaceCreateInfoKHR createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.dpy = p.first;
|
||||
createInfo.window = p.second;
|
||||
CHECK_RESULT(vkCreateXlibSurfaceKHR(this->m_instance, &createInfo, nullptr, &surface));
|
||||
}
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
, [&](std::pair<wl_display*, wl_surface*> p)
|
||||
{
|
||||
VkWaylandSurfaceCreateInfoKHR createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.display = p.first;
|
||||
createInfo.surface = p.second;
|
||||
CHECK_RESULT(vkCreateWaylandSurfaceKHR(this->m_instance, &createInfo, nullptr, &surface));
|
||||
}
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
|
||||
uint32_t device_queues = dev.get_queue_count();
|
||||
|
@ -1439,7 +1455,7 @@ namespace vk
|
|||
void destroy()
|
||||
{
|
||||
if (!pool) return;
|
||||
|
||||
|
||||
vkDestroyDescriptorPool((*owner), pool, nullptr);
|
||||
owner = nullptr;
|
||||
pool = nullptr;
|
||||
|
@ -1591,7 +1607,7 @@ namespace vk
|
|||
{
|
||||
::glsl::program_domain domain;
|
||||
program_input_type type;
|
||||
|
||||
|
||||
bound_buffer as_buffer;
|
||||
bound_sampler as_sampler;
|
||||
|
||||
|
|
|
@ -145,7 +145,6 @@ void fmt_class_string<video_aspect>::format(std::string& out, u64 arg)
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void fmt_class_string<keyboard_handler>::format(std::string& out, u64 arg)
|
||||
{
|
||||
|
|
66
rpcs3/cmake_modules/FindWayland.cmake
Normal file
66
rpcs3/cmake_modules/FindWayland.cmake
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Try to find Wayland on a Unix system
|
||||
#
|
||||
# This will define:
|
||||
#
|
||||
# WAYLAND_FOUND - True if Wayland is found
|
||||
# WAYLAND_LIBRARIES - Link these to use Wayland
|
||||
# WAYLAND_INCLUDE_DIR - Include directory for Wayland
|
||||
# WAYLAND_DEFINITIONS - Compiler flags for using Wayland
|
||||
#
|
||||
# In addition the following more fine grained variables will be defined:
|
||||
#
|
||||
# WAYLAND_CLIENT_FOUND WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES
|
||||
# WAYLAND_SERVER_FOUND WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES
|
||||
# WAYLAND_EGL_FOUND WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES
|
||||
#
|
||||
# Copyright (c) 2013 Martin Gräßlin <mgraesslin@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
IF (NOT WIN32)
|
||||
IF (WAYLAND_INCLUDE_DIR AND WAYLAND_LIBRARIES)
|
||||
# In the cache already
|
||||
SET(WAYLAND_FIND_QUIETLY TRUE)
|
||||
ENDIF ()
|
||||
|
||||
# Use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
FIND_PACKAGE(PkgConfig)
|
||||
PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor)
|
||||
|
||||
SET(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS})
|
||||
|
||||
FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
|
||||
FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
|
||||
FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
|
||||
FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
|
||||
|
||||
FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
|
||||
FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
|
||||
FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
|
||||
FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
|
||||
|
||||
set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR} ${WAYLAND_CURSOR_INCLUDE_DIR})
|
||||
|
||||
set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES})
|
||||
|
||||
list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
WAYLAND_INCLUDE_DIR WAYLAND_LIBRARIES
|
||||
WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES
|
||||
WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES
|
||||
WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES
|
||||
WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES
|
||||
)
|
||||
|
||||
ENDIF ()
|
|
@ -1,7 +1,4 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "ds4_pad_handler.h"
|
||||
#include "rpcs3qt/pad_settings_dialog.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
|
@ -82,8 +79,10 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
ds4_pad_handler::ds4_pad_handler() : is_init(false)
|
||||
ds4_pad_handler::ds4_pad_handler() : PadHandlerBase(pad_handler::ds4)
|
||||
{
|
||||
init_configs();
|
||||
|
||||
// Define border values
|
||||
thumb_min = 0;
|
||||
thumb_max = 255;
|
||||
|
@ -92,52 +91,6 @@ ds4_pad_handler::ds4_pad_handler() : is_init(false)
|
|||
vibration_min = 0;
|
||||
vibration_max = 255;
|
||||
|
||||
// Set this handler's type and save location
|
||||
m_pad_config.cfg_type = "ds4";
|
||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_ds4.yml";
|
||||
|
||||
// Set default button mapping
|
||||
m_pad_config.ls_left.def = button_list.at(DS4KeyCodes::LSXNeg);
|
||||
m_pad_config.ls_down.def = button_list.at(DS4KeyCodes::LSYNeg);
|
||||
m_pad_config.ls_right.def = button_list.at(DS4KeyCodes::LSXPos);
|
||||
m_pad_config.ls_up.def = button_list.at(DS4KeyCodes::LSYPos);
|
||||
m_pad_config.rs_left.def = button_list.at(DS4KeyCodes::RSXNeg);
|
||||
m_pad_config.rs_down.def = button_list.at(DS4KeyCodes::RSYNeg);
|
||||
m_pad_config.rs_right.def = button_list.at(DS4KeyCodes::RSXPos);
|
||||
m_pad_config.rs_up.def = button_list.at(DS4KeyCodes::RSYPos);
|
||||
m_pad_config.start.def = button_list.at(DS4KeyCodes::Options);
|
||||
m_pad_config.select.def = button_list.at(DS4KeyCodes::Share);
|
||||
m_pad_config.ps.def = button_list.at(DS4KeyCodes::PSButton);
|
||||
m_pad_config.square.def = button_list.at(DS4KeyCodes::Square);
|
||||
m_pad_config.cross.def = button_list.at(DS4KeyCodes::Cross);
|
||||
m_pad_config.circle.def = button_list.at(DS4KeyCodes::Circle);
|
||||
m_pad_config.triangle.def = button_list.at(DS4KeyCodes::Triangle);
|
||||
m_pad_config.left.def = button_list.at(DS4KeyCodes::Left);
|
||||
m_pad_config.down.def = button_list.at(DS4KeyCodes::Down);
|
||||
m_pad_config.right.def = button_list.at(DS4KeyCodes::Right);
|
||||
m_pad_config.up.def = button_list.at(DS4KeyCodes::Up);
|
||||
m_pad_config.r1.def = button_list.at(DS4KeyCodes::R1);
|
||||
m_pad_config.r2.def = button_list.at(DS4KeyCodes::R2);
|
||||
m_pad_config.r3.def = button_list.at(DS4KeyCodes::R3);
|
||||
m_pad_config.l1.def = button_list.at(DS4KeyCodes::L1);
|
||||
m_pad_config.l2.def = button_list.at(DS4KeyCodes::L2);
|
||||
m_pad_config.l3.def = button_list.at(DS4KeyCodes::L3);
|
||||
|
||||
// Set default misc variables
|
||||
m_pad_config.lstickdeadzone.def = 40; // between 0 and 255
|
||||
m_pad_config.rstickdeadzone.def = 40; // between 0 and 255
|
||||
m_pad_config.ltriggerthreshold.def = 0; // between 0 and 255
|
||||
m_pad_config.rtriggerthreshold.def = 0; // between 0 and 255
|
||||
m_pad_config.padsquircling.def = 8000;
|
||||
|
||||
// Set color value
|
||||
m_pad_config.colorR.def = 0;
|
||||
m_pad_config.colorG.def = 0;
|
||||
m_pad_config.colorB.def = 20;
|
||||
|
||||
// apply defaults
|
||||
m_pad_config.from_default();
|
||||
|
||||
// set capabilities
|
||||
b_has_config = true;
|
||||
b_has_rumble = true;
|
||||
|
@ -147,6 +100,54 @@ ds4_pad_handler::ds4_pad_handler() : is_init(false)
|
|||
m_thumb_threshold = thumb_max / 2;
|
||||
}
|
||||
|
||||
void ds4_pad_handler::init_config(pad_config* cfg, const std::string& name)
|
||||
{
|
||||
// Set this profile's save location
|
||||
cfg->cfg_name = name;
|
||||
|
||||
// Set default button mapping
|
||||
cfg->ls_left.def = button_list.at(DS4KeyCodes::LSXNeg);
|
||||
cfg->ls_down.def = button_list.at(DS4KeyCodes::LSYNeg);
|
||||
cfg->ls_right.def = button_list.at(DS4KeyCodes::LSXPos);
|
||||
cfg->ls_up.def = button_list.at(DS4KeyCodes::LSYPos);
|
||||
cfg->rs_left.def = button_list.at(DS4KeyCodes::RSXNeg);
|
||||
cfg->rs_down.def = button_list.at(DS4KeyCodes::RSYNeg);
|
||||
cfg->rs_right.def = button_list.at(DS4KeyCodes::RSXPos);
|
||||
cfg->rs_up.def = button_list.at(DS4KeyCodes::RSYPos);
|
||||
cfg->start.def = button_list.at(DS4KeyCodes::Options);
|
||||
cfg->select.def = button_list.at(DS4KeyCodes::Share);
|
||||
cfg->ps.def = button_list.at(DS4KeyCodes::PSButton);
|
||||
cfg->square.def = button_list.at(DS4KeyCodes::Square);
|
||||
cfg->cross.def = button_list.at(DS4KeyCodes::Cross);
|
||||
cfg->circle.def = button_list.at(DS4KeyCodes::Circle);
|
||||
cfg->triangle.def = button_list.at(DS4KeyCodes::Triangle);
|
||||
cfg->left.def = button_list.at(DS4KeyCodes::Left);
|
||||
cfg->down.def = button_list.at(DS4KeyCodes::Down);
|
||||
cfg->right.def = button_list.at(DS4KeyCodes::Right);
|
||||
cfg->up.def = button_list.at(DS4KeyCodes::Up);
|
||||
cfg->r1.def = button_list.at(DS4KeyCodes::R1);
|
||||
cfg->r2.def = button_list.at(DS4KeyCodes::R2);
|
||||
cfg->r3.def = button_list.at(DS4KeyCodes::R3);
|
||||
cfg->l1.def = button_list.at(DS4KeyCodes::L1);
|
||||
cfg->l2.def = button_list.at(DS4KeyCodes::L2);
|
||||
cfg->l3.def = button_list.at(DS4KeyCodes::L3);
|
||||
|
||||
// Set default misc variables
|
||||
cfg->lstickdeadzone.def = 40; // between 0 and 255
|
||||
cfg->rstickdeadzone.def = 40; // between 0 and 255
|
||||
cfg->ltriggerthreshold.def = 0; // between 0 and 255
|
||||
cfg->rtriggerthreshold.def = 0; // between 0 and 255
|
||||
cfg->padsquircling.def = 8000;
|
||||
|
||||
// Set color value
|
||||
cfg->colorR.def = 0;
|
||||
cfg->colorG.def = 0;
|
||||
cfg->colorB.def = 20;
|
||||
|
||||
// apply defaults
|
||||
cfg->from_default();
|
||||
}
|
||||
|
||||
void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist, std::vector<std::string> buttons)
|
||||
{
|
||||
if (get_blacklist)
|
||||
|
@ -227,6 +228,21 @@ void ds4_pad_handler::TestVibration(const std::string& padId, u32 largeMotor, u3
|
|||
device->largeVibrate = largeMotor;
|
||||
device->smallVibrate = smallMotor;
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
if (g_cfg_input.player[i]->handler == pad_handler::ds4)
|
||||
{
|
||||
if (g_cfg_input.player[i]->device.to_string() == padId)
|
||||
{
|
||||
m_pad_configs[index].load();
|
||||
device->config = &m_pad_configs[index];
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// Start/Stop the engines :)
|
||||
SendVibrateData(device);
|
||||
}
|
||||
|
@ -259,29 +275,30 @@ void ds4_pad_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val,
|
|||
{
|
||||
// Update the pad button values based on their type and thresholds.
|
||||
// With this you can use axis or triggers as buttons or vice versa
|
||||
auto p_profile = m_dev->config;
|
||||
switch (keyCode)
|
||||
{
|
||||
case DS4KeyCodes::L2:
|
||||
pressed = val > m_pad_config.ltriggerthreshold;
|
||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.ltriggerthreshold) : 0;
|
||||
pressed = val > p_profile->ltriggerthreshold;
|
||||
val = pressed ? NormalizeTriggerInput(val, p_profile->ltriggerthreshold) : 0;
|
||||
break;
|
||||
case DS4KeyCodes::R2:
|
||||
pressed = val > m_pad_config.rtriggerthreshold;
|
||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.rtriggerthreshold) : 0;
|
||||
pressed = val > p_profile->rtriggerthreshold;
|
||||
val = pressed ? NormalizeTriggerInput(val, p_profile->rtriggerthreshold) : 0;
|
||||
break;
|
||||
case DS4KeyCodes::LSXNeg:
|
||||
case DS4KeyCodes::LSXPos:
|
||||
case DS4KeyCodes::LSYNeg:
|
||||
case DS4KeyCodes::LSYPos:
|
||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.lstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, m_pad_config.lstickdeadzone, ignore_threshold) : 0;
|
||||
pressed = val > (ignore_threshold ? 0 : p_profile->lstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, p_profile->lstickdeadzone, ignore_threshold) : 0;
|
||||
break;
|
||||
case DS4KeyCodes::RSXNeg:
|
||||
case DS4KeyCodes::RSXPos:
|
||||
case DS4KeyCodes::RSYNeg:
|
||||
case DS4KeyCodes::RSYPos:
|
||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.rstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, m_pad_config.rstickdeadzone, ignore_threshold) : 0;
|
||||
pressed = val > (ignore_threshold ? 0 : p_profile->rstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, p_profile->rstickdeadzone, ignore_threshold) : 0;
|
||||
break;
|
||||
default: // normal button (should in theory also support sensitive buttons)
|
||||
pressed = val > 0;
|
||||
|
@ -406,8 +423,8 @@ void ds4_pad_handler::ProcessDataToPad(const std::shared_ptr<DS4Device>& device,
|
|||
pad->m_cable_state = device->cableState;
|
||||
|
||||
auto buf = device->padData;
|
||||
|
||||
auto button_values = GetButtonValues(device);
|
||||
auto p_profile = device->config;
|
||||
|
||||
// Translate any corresponding keycodes to our normal DS3 buttons and triggers
|
||||
for (auto & btn : pad->m_buttons)
|
||||
|
@ -428,7 +445,7 @@ void ds4_pad_handler::ProcessDataToPad(const std::shared_ptr<DS4Device>& device,
|
|||
#endif
|
||||
|
||||
// used to get the absolute value of an axis
|
||||
float stick_val[4];
|
||||
s32 stick_val[4];
|
||||
|
||||
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
|
||||
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
||||
|
@ -452,13 +469,13 @@ void ds4_pad_handler::ProcessDataToPad(const std::shared_ptr<DS4Device>& device,
|
|||
u16 lx, ly, rx, ry;
|
||||
|
||||
// Normalize our two stick's axis based on the thresholds
|
||||
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], m_pad_config.lstickdeadzone);
|
||||
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], m_pad_config.rstickdeadzone);
|
||||
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], p_profile->lstickdeadzone);
|
||||
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], p_profile->rstickdeadzone);
|
||||
|
||||
if (m_pad_config.padsquircling != 0)
|
||||
if (p_profile->padsquircling != 0)
|
||||
{
|
||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, m_pad_config.padsquircling);
|
||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, m_pad_config.padsquircling);
|
||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, p_profile->padsquircling);
|
||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, p_profile->padsquircling);
|
||||
}
|
||||
|
||||
ly = 255 - ly;
|
||||
|
@ -654,6 +671,10 @@ ds4_pad_handler::~ds4_pad_handler()
|
|||
|
||||
int ds4_pad_handler::SendVibrateData(const std::shared_ptr<DS4Device>& device)
|
||||
{
|
||||
auto p_profile = device->config;
|
||||
if (p_profile == nullptr)
|
||||
return -2; // hid_write and hid_write_control return -1 on error
|
||||
|
||||
std::array<u8, 78> outputBuf{0};
|
||||
// write rumble state
|
||||
if (device->btCon)
|
||||
|
@ -663,9 +684,9 @@ int ds4_pad_handler::SendVibrateData(const std::shared_ptr<DS4Device>& device)
|
|||
outputBuf[3] = 0x07;
|
||||
outputBuf[6] = device->smallVibrate;
|
||||
outputBuf[7] = device->largeVibrate;
|
||||
outputBuf[8] = m_pad_config.colorR; // red
|
||||
outputBuf[9] = m_pad_config.colorG; // green
|
||||
outputBuf[10] = m_pad_config.colorB; // blue
|
||||
outputBuf[8] = p_profile->colorR; // red
|
||||
outputBuf[9] = p_profile->colorG; // green
|
||||
outputBuf[10] = p_profile->colorB; // blue
|
||||
|
||||
// alternating blink states with values 0-255: only setting both to zero disables blinking
|
||||
// 255 is roughly 2 seconds, so setting both values to 255 results in a 4 second interval
|
||||
|
@ -690,9 +711,9 @@ int ds4_pad_handler::SendVibrateData(const std::shared_ptr<DS4Device>& device)
|
|||
outputBuf[1] = 0x07;
|
||||
outputBuf[4] = device->smallVibrate;
|
||||
outputBuf[5] = device->largeVibrate;
|
||||
outputBuf[6] = m_pad_config.colorR; // red
|
||||
outputBuf[7] = m_pad_config.colorG; // green
|
||||
outputBuf[8] = m_pad_config.colorB; // blue
|
||||
outputBuf[6] = p_profile->colorR; // red
|
||||
outputBuf[7] = p_profile->colorG; // green
|
||||
outputBuf[8] = p_profile->colorB; // blue
|
||||
outputBuf[9] = device->led_delay_on;
|
||||
outputBuf[10] = device->led_delay_off;
|
||||
|
||||
|
@ -734,10 +755,6 @@ bool ds4_pad_handler::Init()
|
|||
else
|
||||
LOG_SUCCESS(HLE, "[DS4] Controllers found: %d", controllers.size());
|
||||
|
||||
m_pad_config.load();
|
||||
if (!m_pad_config.exist())
|
||||
m_pad_config.save();
|
||||
|
||||
is_init = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -763,7 +780,12 @@ bool ds4_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::strin
|
|||
if (ds4device == nullptr || ds4device->hidDevice == nullptr)
|
||||
return false;
|
||||
|
||||
m_pad_config.load();
|
||||
int index = static_cast<int>(bindings.size());
|
||||
m_pad_configs[index].load();
|
||||
ds4device->config = &m_pad_configs[index];
|
||||
pad_config* p_profile = ds4device->config;
|
||||
if (p_profile == nullptr)
|
||||
return false;
|
||||
|
||||
pad->Init
|
||||
(
|
||||
|
@ -774,34 +796,34 @@ bool ds4_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::strin
|
|||
);
|
||||
|
||||
// 'keycode' here is just 0 as we have to manually calculate this
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.l2), CELL_PAD_CTRL_L2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.r2), CELL_PAD_CTRL_R2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->l2), CELL_PAD_CTRL_L2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->r2), CELL_PAD_CTRL_R2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||
|
||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512);
|
||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399);
|
||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Z, 512);
|
||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_G, 512);
|
||||
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, FindKeyCode(button_list, m_pad_config.ls_left), FindKeyCode(button_list, m_pad_config.ls_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, FindKeyCode(button_list, m_pad_config.ls_down), FindKeyCode(button_list, m_pad_config.ls_up));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, FindKeyCode(button_list, m_pad_config.rs_left), FindKeyCode(button_list, m_pad_config.rs_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, FindKeyCode(button_list, m_pad_config.rs_down), FindKeyCode(button_list, m_pad_config.rs_up));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, FindKeyCode(button_list, p_profile->ls_left), FindKeyCode(button_list, p_profile->ls_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, FindKeyCode(button_list, p_profile->ls_down), FindKeyCode(button_list, p_profile->ls_up));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, FindKeyCode(button_list, p_profile->rs_left), FindKeyCode(button_list, p_profile->rs_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, FindKeyCode(button_list, p_profile->rs_down), FindKeyCode(button_list, p_profile->rs_up));
|
||||
|
||||
pad->m_vibrateMotors.emplace_back(true, 0);
|
||||
pad->m_vibrateMotors.emplace_back(false, 0);
|
||||
|
@ -815,13 +837,14 @@ void ds4_pad_handler::ThreadProc()
|
|||
{
|
||||
for (int i = 0; i < static_cast<int>(bindings.size()); i++)
|
||||
{
|
||||
std::shared_ptr<DS4Device> device = bindings[i].first;
|
||||
m_dev = bindings[i].first;
|
||||
auto thepad = bindings[i].second;
|
||||
auto profile = m_dev->config;
|
||||
|
||||
if (device->hidDevice == nullptr)
|
||||
if (m_dev->hidDevice == nullptr)
|
||||
{
|
||||
// try to reconnect
|
||||
hid_device* dev = hid_open_path(device->path.c_str());
|
||||
hid_device* dev = hid_open_path(m_dev->path.c_str());
|
||||
if (dev)
|
||||
{
|
||||
if (last_connection_status[i] == false)
|
||||
|
@ -831,10 +854,10 @@ void ds4_pad_handler::ThreadProc()
|
|||
connected++;
|
||||
}
|
||||
hid_set_nonblocking(dev, 1);
|
||||
device->hidDevice = dev;
|
||||
m_dev->hidDevice = dev;
|
||||
thepad->m_port_status = CELL_PAD_STATUS_CONNECTED|CELL_PAD_STATUS_ASSIGN_CHANGES;
|
||||
if (!device->hasCalibData)
|
||||
device->hasCalibData = GetCalibrationData(device);
|
||||
if (!m_dev->hasCalibData)
|
||||
m_dev->hasCalibData = GetCalibrationData(m_dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -856,53 +879,53 @@ void ds4_pad_handler::ThreadProc()
|
|||
connected++;
|
||||
}
|
||||
|
||||
DS4DataStatus status = GetRawData(device);
|
||||
DS4DataStatus status = GetRawData(m_dev);
|
||||
|
||||
if (status == DS4DataStatus::ReadError)
|
||||
{
|
||||
// this also can mean disconnected, either way deal with it on next loop and reconnect
|
||||
hid_close(device->hidDevice);
|
||||
device->hidDevice = nullptr;
|
||||
hid_close(m_dev->hidDevice);
|
||||
m_dev->hidDevice = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Attempt to send rumble no matter what
|
||||
int idx_l = m_pad_config.switch_vibration_motors ? 1 : 0;
|
||||
int idx_s = m_pad_config.switch_vibration_motors ? 0 : 1;
|
||||
int idx_l = profile->switch_vibration_motors ? 1 : 0;
|
||||
int idx_s = profile->switch_vibration_motors ? 0 : 1;
|
||||
|
||||
int speed_large = m_pad_config.enable_vibration_motor_large ? thepad->m_vibrateMotors[idx_l].m_value : vibration_min;
|
||||
int speed_small = m_pad_config.enable_vibration_motor_small ? thepad->m_vibrateMotors[idx_s].m_value : vibration_min;
|
||||
int speed_large = profile->enable_vibration_motor_large ? thepad->m_vibrateMotors[idx_l].m_value : vibration_min;
|
||||
int speed_small = profile->enable_vibration_motor_small ? thepad->m_vibrateMotors[idx_s].m_value : vibration_min;
|
||||
|
||||
bool wireless = device->cableState < 1;
|
||||
bool lowBattery = device->batteryLevel < 2;
|
||||
bool isBlinking = device->led_delay_on > 0 || device->led_delay_off > 0;
|
||||
bool wireless = m_dev->cableState < 1;
|
||||
bool lowBattery = m_dev->batteryLevel < 2;
|
||||
bool isBlinking = m_dev->led_delay_on > 0 || m_dev->led_delay_off > 0;
|
||||
bool newBlinkData = false;
|
||||
|
||||
// we are now wired or have okay battery level -> stop blinking
|
||||
if (isBlinking && !(wireless && lowBattery))
|
||||
{
|
||||
device->led_delay_on = 0;
|
||||
device->led_delay_off = 0;
|
||||
m_dev->led_delay_on = 0;
|
||||
m_dev->led_delay_off = 0;
|
||||
newBlinkData = true;
|
||||
}
|
||||
// we are now wireless and low on battery -> blink
|
||||
if (!isBlinking && wireless && lowBattery)
|
||||
{
|
||||
device->led_delay_on = 100;
|
||||
device->led_delay_off = 100;
|
||||
m_dev->led_delay_on = 100;
|
||||
m_dev->led_delay_off = 100;
|
||||
newBlinkData = true;
|
||||
}
|
||||
|
||||
device->newVibrateData = device->newVibrateData || device->largeVibrate != speed_large || device->smallVibrate != speed_small || newBlinkData;
|
||||
m_dev->newVibrateData = m_dev->newVibrateData || m_dev->largeVibrate != speed_large || m_dev->smallVibrate != speed_small || newBlinkData;
|
||||
|
||||
device->largeVibrate = speed_large;
|
||||
device->smallVibrate = speed_small;
|
||||
m_dev->largeVibrate = speed_large;
|
||||
m_dev->smallVibrate = speed_small;
|
||||
|
||||
if (device->newVibrateData)
|
||||
if (m_dev->newVibrateData)
|
||||
{
|
||||
if (SendVibrateData(device) >= 0)
|
||||
if (SendVibrateData(m_dev) >= 0)
|
||||
{
|
||||
device->newVibrateData = false;
|
||||
m_dev->newVibrateData = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -911,7 +934,7 @@ void ds4_pad_handler::ThreadProc()
|
|||
continue;
|
||||
|
||||
else if (status == DS4DataStatus::NewData)
|
||||
ProcessDataToPad(device, thepad);
|
||||
ProcessDataToPad(m_dev, thepad);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ class ds4_pad_handler final : public PadHandlerBase
|
|||
struct DS4Device
|
||||
{
|
||||
hid_device* hidDevice{ nullptr };
|
||||
pad_config* config{ nullptr };
|
||||
std::string path{ "" };
|
||||
bool btCon{ false };
|
||||
bool hasCalibData{ false };
|
||||
|
@ -143,12 +144,14 @@ public:
|
|||
void ThreadProc() override;
|
||||
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& buttonCallback, bool get_blacklist = false, std::vector<std::string> buttons = {}) override;
|
||||
void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override;
|
||||
void init_config(pad_config* cfg, const std::string& name) override;
|
||||
|
||||
private:
|
||||
bool is_init;
|
||||
bool is_init = false;
|
||||
|
||||
std::vector<u32> blacklist;
|
||||
std::vector<std::pair<std::shared_ptr<DS4Device>, std::shared_ptr<Pad>>> bindings;
|
||||
std::shared_ptr<DS4Device> m_dev;
|
||||
|
||||
private:
|
||||
std::shared_ptr<DS4Device> GetDevice(const std::string& padId);
|
||||
|
|
|
@ -123,6 +123,7 @@
|
|||
<ClCompile Include="Emu\CPU\CPUTranslator.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Io\PadHandler.cpp" />
|
||||
<ClCompile Include="Emu\PSP2\ARMv7Module.cpp" />
|
||||
<ClCompile Include="Emu\Cell\lv2\lv2.cpp" />
|
||||
<ClCompile Include="Emu\Cell\lv2\sys_cond.cpp" />
|
||||
|
|
|
@ -935,6 +935,9 @@
|
|||
<ClCompile Include="Emu\Cell\lv2\sys_net.cpp">
|
||||
<Filter>Emu\Cell\lv2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Io\PadHandler.cpp">
|
||||
<Filter>Emu\Io</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
evdev_joystick_handler::evdev_joystick_handler()
|
||||
evdev_joystick_handler::evdev_joystick_handler() : PadHandlerBase(pad_handler::evdev)
|
||||
{
|
||||
init_configs();
|
||||
|
||||
// Define border values
|
||||
thumb_min = 0;
|
||||
thumb_max = 255;
|
||||
|
@ -27,47 +29,6 @@ evdev_joystick_handler::evdev_joystick_handler()
|
|||
vibration_min = 0;
|
||||
vibration_max = 65535;
|
||||
|
||||
// Set this handler's type and save location
|
||||
m_pad_config.cfg_type = "evdev";
|
||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_evdev.yml";
|
||||
|
||||
// Set default button mapping
|
||||
m_pad_config.ls_left.def = rev_axis_list.at(ABS_X);
|
||||
m_pad_config.ls_down.def = axis_list.at(ABS_Y);
|
||||
m_pad_config.ls_right.def = axis_list.at(ABS_X);
|
||||
m_pad_config.ls_up.def = rev_axis_list.at(ABS_Y);
|
||||
m_pad_config.rs_left.def = rev_axis_list.at(ABS_RX);
|
||||
m_pad_config.rs_down.def = axis_list.at(ABS_RY);
|
||||
m_pad_config.rs_right.def = axis_list.at(ABS_RX);
|
||||
m_pad_config.rs_up.def = rev_axis_list.at(ABS_RY);
|
||||
m_pad_config.start.def = button_list.at(BTN_START);
|
||||
m_pad_config.select.def = button_list.at(BTN_SELECT);
|
||||
m_pad_config.ps.def = button_list.at(BTN_MODE);
|
||||
m_pad_config.square.def = button_list.at(BTN_X);
|
||||
m_pad_config.cross.def = button_list.at(BTN_A);
|
||||
m_pad_config.circle.def = button_list.at(BTN_B);
|
||||
m_pad_config.triangle.def = button_list.at(BTN_Y);
|
||||
m_pad_config.left.def = rev_axis_list.at(ABS_HAT0X);
|
||||
m_pad_config.down.def = axis_list.at(ABS_HAT0Y);
|
||||
m_pad_config.right.def = axis_list.at(ABS_HAT0X);
|
||||
m_pad_config.up.def = rev_axis_list.at(ABS_HAT0Y);
|
||||
m_pad_config.r1.def = button_list.at(BTN_TR);
|
||||
m_pad_config.r2.def = axis_list.at(ABS_RZ);
|
||||
m_pad_config.r3.def = button_list.at(BTN_THUMBR);
|
||||
m_pad_config.l1.def = button_list.at(BTN_TL);
|
||||
m_pad_config.l2.def = axis_list.at(ABS_Z);
|
||||
m_pad_config.l3.def = button_list.at(BTN_THUMBL);
|
||||
|
||||
// Set default misc variables
|
||||
m_pad_config.lstickdeadzone.def = 30; // between 0 and 255
|
||||
m_pad_config.rstickdeadzone.def = 30; // between 0 and 255
|
||||
m_pad_config.ltriggerthreshold.def = 0; // between 0 and 255
|
||||
m_pad_config.rtriggerthreshold.def = 0; // between 0 and 255
|
||||
m_pad_config.padsquircling.def = 5000;
|
||||
|
||||
// apply defaults
|
||||
m_pad_config.from_default();
|
||||
|
||||
// set capabilities
|
||||
b_has_config = true;
|
||||
b_has_rumble = true;
|
||||
|
@ -82,12 +43,54 @@ evdev_joystick_handler::~evdev_joystick_handler()
|
|||
Close();
|
||||
}
|
||||
|
||||
void evdev_joystick_handler::init_config(pad_config* cfg, const std::string& name)
|
||||
{
|
||||
// Set this profile's save location
|
||||
cfg->cfg_name = name;
|
||||
|
||||
// Set default button mapping
|
||||
cfg->ls_left.def = rev_axis_list.at(ABS_X);
|
||||
cfg->ls_down.def = axis_list.at(ABS_Y);
|
||||
cfg->ls_right.def = axis_list.at(ABS_X);
|
||||
cfg->ls_up.def = rev_axis_list.at(ABS_Y);
|
||||
cfg->rs_left.def = rev_axis_list.at(ABS_RX);
|
||||
cfg->rs_down.def = axis_list.at(ABS_RY);
|
||||
cfg->rs_right.def = axis_list.at(ABS_RX);
|
||||
cfg->rs_up.def = rev_axis_list.at(ABS_RY);
|
||||
cfg->start.def = button_list.at(BTN_START);
|
||||
cfg->select.def = button_list.at(BTN_SELECT);
|
||||
cfg->ps.def = button_list.at(BTN_MODE);
|
||||
cfg->square.def = button_list.at(BTN_X);
|
||||
cfg->cross.def = button_list.at(BTN_A);
|
||||
cfg->circle.def = button_list.at(BTN_B);
|
||||
cfg->triangle.def = button_list.at(BTN_Y);
|
||||
cfg->left.def = rev_axis_list.at(ABS_HAT0X);
|
||||
cfg->down.def = axis_list.at(ABS_HAT0Y);
|
||||
cfg->right.def = axis_list.at(ABS_HAT0X);
|
||||
cfg->up.def = rev_axis_list.at(ABS_HAT0Y);
|
||||
cfg->r1.def = button_list.at(BTN_TR);
|
||||
cfg->r2.def = axis_list.at(ABS_RZ);
|
||||
cfg->r3.def = button_list.at(BTN_THUMBR);
|
||||
cfg->l1.def = button_list.at(BTN_TL);
|
||||
cfg->l2.def = axis_list.at(ABS_Z);
|
||||
cfg->l3.def = button_list.at(BTN_THUMBL);
|
||||
|
||||
// Set default misc variables
|
||||
cfg->lstickdeadzone.def = 30; // between 0 and 255
|
||||
cfg->rstickdeadzone.def = 30; // between 0 and 255
|
||||
cfg->ltriggerthreshold.def = 0; // between 0 and 255
|
||||
cfg->rtriggerthreshold.def = 0; // between 0 and 255
|
||||
cfg->padsquircling.def = 5000;
|
||||
|
||||
// apply defaults
|
||||
cfg->from_default();
|
||||
}
|
||||
|
||||
bool evdev_joystick_handler::Init()
|
||||
{
|
||||
if (m_is_init)
|
||||
return true;
|
||||
|
||||
m_pad_config.load();
|
||||
m_pos_axis_config.load();
|
||||
|
||||
if (!m_pos_axis_config.exist())
|
||||
|
@ -498,6 +501,7 @@ void evdev_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u1
|
|||
{
|
||||
// Update the pad button values based on their type and thresholds.
|
||||
// With this you can use axis or triggers as buttons or vice versa
|
||||
auto profile = m_dev.config;
|
||||
u32 code = static_cast<u32>(keyCode);
|
||||
auto checkButton = [&](const EvdevButton& b)
|
||||
{
|
||||
|
@ -510,23 +514,23 @@ void evdev_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u1
|
|||
|
||||
if (checkButton(m_dev.trigger_left))
|
||||
{
|
||||
pressed = value > m_pad_config.ltriggerthreshold;
|
||||
value = pressed ? NormalizeTriggerInput(value, m_pad_config.ltriggerthreshold) : 0;
|
||||
pressed = value > profile->ltriggerthreshold;
|
||||
value = pressed ? NormalizeTriggerInput(value, profile->ltriggerthreshold) : 0;
|
||||
}
|
||||
else if (checkButton(m_dev.trigger_right))
|
||||
{
|
||||
pressed = value > m_pad_config.rtriggerthreshold;
|
||||
value = pressed ? NormalizeTriggerInput(value, m_pad_config.rtriggerthreshold) : 0;
|
||||
pressed = value > profile->rtriggerthreshold;
|
||||
value = pressed ? NormalizeTriggerInput(value, profile->rtriggerthreshold) : 0;
|
||||
}
|
||||
else if (checkButtons(m_dev.axis_left))
|
||||
{
|
||||
pressed = value > (ignore_threshold ? 0 : m_pad_config.lstickdeadzone);
|
||||
value = pressed ? NormalizeStickInput(value, m_pad_config.lstickdeadzone, ignore_threshold) : 0;
|
||||
pressed = value > (ignore_threshold ? 0 : profile->lstickdeadzone);
|
||||
value = pressed ? NormalizeStickInput(value, profile->lstickdeadzone, ignore_threshold) : 0;
|
||||
}
|
||||
else if (checkButtons(m_dev.axis_right))
|
||||
{
|
||||
pressed = value > (ignore_threshold ? 0 : m_pad_config.rstickdeadzone);
|
||||
value = pressed ? NormalizeStickInput(value, m_pad_config.rstickdeadzone, ignore_threshold) : 0;
|
||||
pressed = value > (ignore_threshold ? 0 : profile->rstickdeadzone);
|
||||
value = pressed ? NormalizeStickInput(value, profile->rstickdeadzone, ignore_threshold) : 0;
|
||||
}
|
||||
else // normal button (should in theory also support sensitive buttons)
|
||||
{
|
||||
|
@ -608,7 +612,7 @@ std::vector<std::string> evdev_joystick_handler::ListDevices()
|
|||
libevdev_has_event_code(dev, EV_ABS, ABS_Y))
|
||||
{
|
||||
// It's a joystick.
|
||||
evdev_joystick_list.push_back(libevdev_get_name(dev));
|
||||
evdev_joystick_list.push_back(et.name + ": " + libevdev_get_name(dev));
|
||||
}
|
||||
libevdev_free(dev);
|
||||
close(fd);
|
||||
|
@ -643,7 +647,7 @@ int evdev_joystick_handler::add_device(const std::string& device, bool in_settin
|
|||
close(fd);
|
||||
continue;
|
||||
}
|
||||
const std::string name = libevdev_get_name(dev);
|
||||
const std::string name = et.name + ": " + libevdev_get_name(dev);
|
||||
if (libevdev_has_event_type(dev, EV_KEY) &&
|
||||
libevdev_has_event_code(dev, EV_ABS, ABS_X) &&
|
||||
libevdev_has_event_code(dev, EV_ABS, ABS_Y) &&
|
||||
|
@ -680,6 +684,7 @@ void evdev_joystick_handler::ThreadProc()
|
|||
for (auto& device : devices)
|
||||
{
|
||||
m_dev = device;
|
||||
auto profile = device.config;
|
||||
auto pad = device.pad;
|
||||
auto axis_orientations = device.axis_orientations;
|
||||
auto& dev = device.device;
|
||||
|
@ -704,10 +709,10 @@ void evdev_joystick_handler::ThreadProc()
|
|||
padnum++;
|
||||
|
||||
// Handle vibration
|
||||
int idx_l = m_pad_config.switch_vibration_motors ? 1 : 0;
|
||||
int idx_s = m_pad_config.switch_vibration_motors ? 0 : 1;
|
||||
u16 force_large = m_pad_config.enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value * 257 : vibration_min;
|
||||
u16 force_small = m_pad_config.enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value * 257 : vibration_min;
|
||||
int idx_l = profile->switch_vibration_motors ? 1 : 0;
|
||||
int idx_s = profile->switch_vibration_motors ? 0 : 1;
|
||||
u16 force_large = profile->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value * 257 : vibration_min;
|
||||
u16 force_small = profile->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value * 257 : vibration_min;
|
||||
SetRumble(&device, force_large, force_small);
|
||||
|
||||
// Try to query the latest event from the joystick.
|
||||
|
@ -832,13 +837,13 @@ void evdev_joystick_handler::ThreadProc()
|
|||
u16 lx, ly, rx, ry;
|
||||
|
||||
// Normalize our two stick's axis based on the thresholds
|
||||
std::tie(lx, ly) = NormalizeStickDeadzone(device.stick_val[0], device.stick_val[1], m_pad_config.lstickdeadzone);
|
||||
std::tie(rx, ry) = NormalizeStickDeadzone(device.stick_val[2], device.stick_val[3], m_pad_config.rstickdeadzone);
|
||||
std::tie(lx, ly) = NormalizeStickDeadzone(device.stick_val[0], device.stick_val[1], profile->lstickdeadzone);
|
||||
std::tie(rx, ry) = NormalizeStickDeadzone(device.stick_val[2], device.stick_val[3], profile->rstickdeadzone);
|
||||
|
||||
if (m_pad_config.padsquircling != 0)
|
||||
if (profile->padsquircling != 0)
|
||||
{
|
||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, m_pad_config.padsquircling);
|
||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, m_pad_config.padsquircling);
|
||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, profile->padsquircling);
|
||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, profile->padsquircling);
|
||||
}
|
||||
|
||||
pad->m_sticks[0].m_value = lx;
|
||||
|
@ -866,6 +871,13 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std
|
|||
int i = 0; // increment to know the axis location (17-24). Be careful if you ever add more find_key() calls in here (BUTTON_COUNT = 17)
|
||||
int last_type = EV_ABS;
|
||||
|
||||
int index = static_cast<int>(devices.size());
|
||||
m_pad_configs[index].load();
|
||||
m_dev.config = &m_pad_configs[index];
|
||||
pad_config* p_profile = m_dev.config;
|
||||
if (p_profile == nullptr)
|
||||
return false;
|
||||
|
||||
auto find_key = [&](const cfg::string& name)
|
||||
{
|
||||
int type = EV_ABS;
|
||||
|
@ -909,38 +921,38 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std
|
|||
CELL_PAD_DEV_TYPE_STANDARD
|
||||
);
|
||||
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||
|
||||
m_dev.trigger_left = evdevbutton(m_pad_config.l2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev.trigger_left.code, CELL_PAD_CTRL_L2);
|
||||
m_dev.trigger_left = evdevbutton(p_profile->l2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev.trigger_left.code, CELL_PAD_CTRL_L2);
|
||||
|
||||
m_dev.trigger_right = evdevbutton(m_pad_config.r2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev.trigger_right.code, CELL_PAD_CTRL_R2);
|
||||
m_dev.trigger_right = evdevbutton(p_profile->r2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev.trigger_right.code, CELL_PAD_CTRL_R2);
|
||||
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||
|
||||
m_dev.axis_left[0] = evdevbutton(m_pad_config.ls_right);
|
||||
m_dev.axis_left[1] = evdevbutton(m_pad_config.ls_left);
|
||||
m_dev.axis_left[2] = evdevbutton(m_pad_config.ls_up);
|
||||
m_dev.axis_left[3] = evdevbutton(m_pad_config.ls_down);
|
||||
m_dev.axis_right[0] = evdevbutton(m_pad_config.rs_right);
|
||||
m_dev.axis_right[1] = evdevbutton(m_pad_config.rs_left);
|
||||
m_dev.axis_right[2] = evdevbutton(m_pad_config.rs_up);
|
||||
m_dev.axis_right[3] = evdevbutton(m_pad_config.rs_down);
|
||||
m_dev.axis_left[0] = evdevbutton(p_profile->ls_right);
|
||||
m_dev.axis_left[1] = evdevbutton(p_profile->ls_left);
|
||||
m_dev.axis_left[2] = evdevbutton(p_profile->ls_up);
|
||||
m_dev.axis_left[3] = evdevbutton(p_profile->ls_down);
|
||||
m_dev.axis_right[0] = evdevbutton(p_profile->rs_right);
|
||||
m_dev.axis_right[1] = evdevbutton(p_profile->rs_left);
|
||||
m_dev.axis_right[2] = evdevbutton(p_profile->rs_up);
|
||||
m_dev.axis_right[3] = evdevbutton(p_profile->rs_down);
|
||||
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, m_dev.axis_left[1].code, m_dev.axis_left[0].code);
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, m_dev.axis_left[3].code, m_dev.axis_left[2].code);
|
||||
|
|
|
@ -302,11 +302,12 @@ class evdev_joystick_handler final : public PadHandlerBase
|
|||
|
||||
struct EvdevDevice
|
||||
{
|
||||
libevdev* device = nullptr;
|
||||
libevdev* device{ nullptr };
|
||||
pad_config* config{ nullptr };
|
||||
std::string path;
|
||||
std::shared_ptr<Pad> pad;
|
||||
std::unordered_map<int, bool> axis_orientations; // value is true if key was found in rev_axis_list
|
||||
float stick_val[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
s32 stick_val[4] = { 0, 0, 0, 0 };
|
||||
u16 val_min[4] = { 0, 0, 0, 0 };
|
||||
u16 val_max[4] = { 0, 0, 0, 0 };
|
||||
EvdevButton trigger_left = { 0, 0, 0 };
|
||||
|
@ -328,6 +329,7 @@ public:
|
|||
evdev_joystick_handler();
|
||||
~evdev_joystick_handler();
|
||||
|
||||
void init_config(pad_config* cfg, const std::string& name) override;
|
||||
bool Init() override;
|
||||
std::vector<std::string> ListDevices() override;
|
||||
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#include "keyboard_pad_handler.h"
|
||||
#include "keyboard_pad_handler.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "rpcs3qt/pad_settings_dialog.h"
|
||||
|
||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
|
||||
|
@ -14,46 +10,50 @@ bool keyboard_pad_handler::Init()
|
|||
return true;
|
||||
}
|
||||
|
||||
keyboard_pad_handler::keyboard_pad_handler() : QObject()
|
||||
keyboard_pad_handler::keyboard_pad_handler() : PadHandlerBase(pad_handler::keyboard), QObject()
|
||||
{
|
||||
// Set this handler's type and save location
|
||||
m_pad_config.cfg_type = "keyboard";
|
||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_kbpad_qt.yml";
|
||||
|
||||
// Set default button mapping
|
||||
m_pad_config.ls_left.def = GetKeyName(Qt::Key_A);
|
||||
m_pad_config.ls_down.def = GetKeyName(Qt::Key_S);
|
||||
m_pad_config.ls_right.def = GetKeyName(Qt::Key_D);
|
||||
m_pad_config.ls_up.def = GetKeyName(Qt::Key_W);
|
||||
m_pad_config.rs_left.def = GetKeyName(Qt::Key_Home);
|
||||
m_pad_config.rs_down.def = GetKeyName(Qt::Key_PageDown);
|
||||
m_pad_config.rs_right.def = GetKeyName(Qt::Key_End);
|
||||
m_pad_config.rs_up.def = GetKeyName(Qt::Key_PageUp);
|
||||
m_pad_config.start.def = GetKeyName(Qt::Key_Return);
|
||||
m_pad_config.select.def = GetKeyName(Qt::Key_Space);
|
||||
m_pad_config.ps.def = GetKeyName(Qt::Key_Backspace);
|
||||
m_pad_config.square.def = GetKeyName(Qt::Key_Z);
|
||||
m_pad_config.cross.def = GetKeyName(Qt::Key_X);
|
||||
m_pad_config.circle.def = GetKeyName(Qt::Key_C);
|
||||
m_pad_config.triangle.def = GetKeyName(Qt::Key_V);
|
||||
m_pad_config.left.def = GetKeyName(Qt::Key_Left);
|
||||
m_pad_config.down.def = GetKeyName(Qt::Key_Down);
|
||||
m_pad_config.right.def = GetKeyName(Qt::Key_Right);
|
||||
m_pad_config.up.def = GetKeyName(Qt::Key_Up);
|
||||
m_pad_config.r1.def = GetKeyName(Qt::Key_E);
|
||||
m_pad_config.r2.def = GetKeyName(Qt::Key_T);
|
||||
m_pad_config.r3.def = GetKeyName(Qt::Key_G);
|
||||
m_pad_config.l1.def = GetKeyName(Qt::Key_Q);
|
||||
m_pad_config.l2.def = GetKeyName(Qt::Key_R);
|
||||
m_pad_config.l3.def = GetKeyName(Qt::Key_F);
|
||||
|
||||
// apply defaults
|
||||
m_pad_config.from_default();
|
||||
init_configs();
|
||||
|
||||
// set capabilities
|
||||
b_has_config = true;
|
||||
}
|
||||
|
||||
void keyboard_pad_handler::init_config(pad_config* cfg, const std::string& name)
|
||||
{
|
||||
// Set this profile's save location
|
||||
cfg->cfg_name = name;
|
||||
|
||||
// Set default button mapping
|
||||
cfg->ls_left.def = GetKeyName(Qt::Key_A);
|
||||
cfg->ls_down.def = GetKeyName(Qt::Key_S);
|
||||
cfg->ls_right.def = GetKeyName(Qt::Key_D);
|
||||
cfg->ls_up.def = GetKeyName(Qt::Key_W);
|
||||
cfg->rs_left.def = GetKeyName(Qt::Key_Home);
|
||||
cfg->rs_down.def = GetKeyName(Qt::Key_PageDown);
|
||||
cfg->rs_right.def = GetKeyName(Qt::Key_End);
|
||||
cfg->rs_up.def = GetKeyName(Qt::Key_PageUp);
|
||||
cfg->start.def = GetKeyName(Qt::Key_Return);
|
||||
cfg->select.def = GetKeyName(Qt::Key_Space);
|
||||
cfg->ps.def = GetKeyName(Qt::Key_Backspace);
|
||||
cfg->square.def = GetKeyName(Qt::Key_Z);
|
||||
cfg->cross.def = GetKeyName(Qt::Key_X);
|
||||
cfg->circle.def = GetKeyName(Qt::Key_C);
|
||||
cfg->triangle.def = GetKeyName(Qt::Key_V);
|
||||
cfg->left.def = GetKeyName(Qt::Key_Left);
|
||||
cfg->down.def = GetKeyName(Qt::Key_Down);
|
||||
cfg->right.def = GetKeyName(Qt::Key_Right);
|
||||
cfg->up.def = GetKeyName(Qt::Key_Up);
|
||||
cfg->r1.def = GetKeyName(Qt::Key_E);
|
||||
cfg->r2.def = GetKeyName(Qt::Key_T);
|
||||
cfg->r3.def = GetKeyName(Qt::Key_G);
|
||||
cfg->l1.def = GetKeyName(Qt::Key_Q);
|
||||
cfg->l2.def = GetKeyName(Qt::Key_R);
|
||||
cfg->l3.def = GetKeyName(Qt::Key_F);
|
||||
|
||||
// apply defaults
|
||||
cfg->from_default();
|
||||
}
|
||||
|
||||
void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
|
||||
{
|
||||
value = Clamp0To255(value);
|
||||
|
@ -65,30 +65,23 @@ void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
|
|||
if (button.m_keyCode != code)
|
||||
continue;
|
||||
|
||||
//Todo: Is this flush necessary once games hit decent speeds?
|
||||
if (button.m_pressed && !pressed)
|
||||
{
|
||||
button.m_flush = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
button.m_pressed = pressed;
|
||||
if (pressed)
|
||||
button.m_value = value;
|
||||
else
|
||||
button.m_value = 0;
|
||||
}
|
||||
button.m_pressed = pressed;
|
||||
button.m_value = pressed ? value : 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
||||
{
|
||||
if (pad->m_sticks[i].m_keyCodeMax == code)
|
||||
bool is_max = pad->m_sticks[i].m_keyCodeMax == code;
|
||||
bool is_min = pad->m_sticks[i].m_keyCodeMin == code;
|
||||
|
||||
if (is_max)
|
||||
m_stick_max[i] = pressed ? 255 : 128;
|
||||
|
||||
if (pad->m_sticks[i].m_keyCodeMin == code)
|
||||
if (is_min)
|
||||
m_stick_min[i] = pressed ? 128 : 0;
|
||||
|
||||
pad->m_sticks[i].m_value = m_stick_max[i] - m_stick_min[i];
|
||||
if (is_max || is_min)
|
||||
pad->m_sticks[i].m_value = m_stick_max[i] - m_stick_min[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -386,7 +379,11 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::
|
|||
if (device != "Keyboard")
|
||||
return false;
|
||||
|
||||
m_pad_config.load();
|
||||
int index = static_cast<int>(bindings.size());
|
||||
m_pad_configs[index].load();
|
||||
pad_config* p_profile = &m_pad_configs[index];
|
||||
if (p_profile == nullptr)
|
||||
return false;
|
||||
|
||||
auto find_key = [&](const cfg::string& name)
|
||||
{
|
||||
|
@ -407,29 +404,29 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::
|
|||
CELL_PAD_DEV_TYPE_STANDARD
|
||||
);
|
||||
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r2), CELL_PAD_CTRL_R2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l2), CELL_PAD_CTRL_L2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->r2), CELL_PAD_CTRL_R2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->l2), CELL_PAD_CTRL_L2);
|
||||
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, find_key(m_pad_config.ls_left), find_key(m_pad_config.ls_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, find_key(m_pad_config.ls_up), find_key(m_pad_config.ls_down));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, find_key(m_pad_config.rs_left), find_key(m_pad_config.rs_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, find_key(m_pad_config.rs_up), find_key(m_pad_config.rs_down));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, find_key(p_profile->ls_left), find_key(p_profile->ls_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, find_key(p_profile->ls_up), find_key(p_profile->ls_down));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, find_key(p_profile->rs_left), find_key(p_profile->rs_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, find_key(p_profile->rs_up), find_key(p_profile->rs_down));
|
||||
|
||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512);
|
||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399);
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include "Utilities/Config.h"
|
||||
#include "Emu/Io/PadHandler.h"
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include <QWindow>
|
||||
#include <QKeyEvent>
|
||||
|
@ -57,6 +55,7 @@ public:
|
|||
|
||||
bool eventFilter(QObject* obj, QEvent* ev) override;
|
||||
|
||||
void init_config(pad_config* cfg, const std::string& name) override;
|
||||
std::vector<std::string> ListDevices() override;
|
||||
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
|
||||
void ThreadProc() override;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#include "stdafx.h"
|
||||
#ifdef _WIN32
|
||||
#include "mm_joystick_handler.h"
|
||||
|
||||
mm_joystick_handler::mm_joystick_handler() : is_init(false)
|
||||
mm_joystick_handler::mm_joystick_handler() : PadHandlerBase(pad_handler::mm)
|
||||
{
|
||||
init_configs();
|
||||
|
||||
// Define border values
|
||||
thumb_min = 0;
|
||||
thumb_max = 255;
|
||||
|
@ -12,47 +13,6 @@ mm_joystick_handler::mm_joystick_handler() : is_init(false)
|
|||
vibration_min = 0;
|
||||
vibration_max = 65535;
|
||||
|
||||
// Set this handler's type and save location
|
||||
m_pad_config.cfg_type = "mmjoystick";
|
||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_mmjoystick.yml";
|
||||
|
||||
// Set default button mapping
|
||||
m_pad_config.ls_left.def = axis_list.at(mmjoy_axis::joy_x_neg);
|
||||
m_pad_config.ls_down.def = axis_list.at(mmjoy_axis::joy_y_neg);
|
||||
m_pad_config.ls_right.def = axis_list.at(mmjoy_axis::joy_x_pos);
|
||||
m_pad_config.ls_up.def = axis_list.at(mmjoy_axis::joy_y_pos);
|
||||
m_pad_config.rs_left.def = axis_list.at(mmjoy_axis::joy_z_neg);
|
||||
m_pad_config.rs_down.def = axis_list.at(mmjoy_axis::joy_r_neg);
|
||||
m_pad_config.rs_right.def = axis_list.at(mmjoy_axis::joy_z_pos);
|
||||
m_pad_config.rs_up.def = axis_list.at(mmjoy_axis::joy_r_pos);
|
||||
m_pad_config.start.def = button_list.at(JOY_BUTTON9);
|
||||
m_pad_config.select.def = button_list.at(JOY_BUTTON10);
|
||||
m_pad_config.ps.def = button_list.at(JOY_BUTTON17);
|
||||
m_pad_config.square.def = button_list.at(JOY_BUTTON4);
|
||||
m_pad_config.cross.def = button_list.at(JOY_BUTTON3);
|
||||
m_pad_config.circle.def = button_list.at(JOY_BUTTON2);
|
||||
m_pad_config.triangle.def = button_list.at(JOY_BUTTON1);
|
||||
m_pad_config.left.def = pov_list.at(JOY_POVLEFT);
|
||||
m_pad_config.down.def = pov_list.at(JOY_POVBACKWARD);
|
||||
m_pad_config.right.def = pov_list.at(JOY_POVRIGHT);
|
||||
m_pad_config.up.def = pov_list.at(JOY_POVFORWARD);
|
||||
m_pad_config.r1.def = button_list.at(JOY_BUTTON8);
|
||||
m_pad_config.r2.def = button_list.at(JOY_BUTTON6);
|
||||
m_pad_config.r3.def = button_list.at(JOY_BUTTON12);
|
||||
m_pad_config.l1.def = button_list.at(JOY_BUTTON7);
|
||||
m_pad_config.l2.def = button_list.at(JOY_BUTTON5);
|
||||
m_pad_config.l3.def = button_list.at(JOY_BUTTON11);
|
||||
|
||||
// Set default misc variables
|
||||
m_pad_config.lstickdeadzone.def = 0; // between 0 and 255
|
||||
m_pad_config.rstickdeadzone.def = 0; // between 0 and 255
|
||||
m_pad_config.ltriggerthreshold.def = 0; // between 0 and 255
|
||||
m_pad_config.rtriggerthreshold.def = 0; // between 0 and 255
|
||||
m_pad_config.padsquircling.def = 8000;
|
||||
|
||||
// apply defaults
|
||||
m_pad_config.from_default();
|
||||
|
||||
// set capabilities
|
||||
b_has_config = true;
|
||||
b_has_rumble = true;
|
||||
|
@ -66,24 +26,66 @@ mm_joystick_handler::~mm_joystick_handler()
|
|||
{
|
||||
}
|
||||
|
||||
void mm_joystick_handler::init_config(pad_config* cfg, const std::string& name)
|
||||
{
|
||||
// Set this profile's save location
|
||||
cfg->cfg_name = name;
|
||||
|
||||
// Set default button mapping
|
||||
cfg->ls_left.def = axis_list.at(mmjoy_axis::joy_x_neg);
|
||||
cfg->ls_down.def = axis_list.at(mmjoy_axis::joy_y_neg);
|
||||
cfg->ls_right.def = axis_list.at(mmjoy_axis::joy_x_pos);
|
||||
cfg->ls_up.def = axis_list.at(mmjoy_axis::joy_y_pos);
|
||||
cfg->rs_left.def = axis_list.at(mmjoy_axis::joy_z_neg);
|
||||
cfg->rs_down.def = axis_list.at(mmjoy_axis::joy_r_neg);
|
||||
cfg->rs_right.def = axis_list.at(mmjoy_axis::joy_z_pos);
|
||||
cfg->rs_up.def = axis_list.at(mmjoy_axis::joy_r_pos);
|
||||
cfg->start.def = button_list.at(JOY_BUTTON9);
|
||||
cfg->select.def = button_list.at(JOY_BUTTON10);
|
||||
cfg->ps.def = button_list.at(JOY_BUTTON17);
|
||||
cfg->square.def = button_list.at(JOY_BUTTON4);
|
||||
cfg->cross.def = button_list.at(JOY_BUTTON3);
|
||||
cfg->circle.def = button_list.at(JOY_BUTTON2);
|
||||
cfg->triangle.def = button_list.at(JOY_BUTTON1);
|
||||
cfg->left.def = pov_list.at(JOY_POVLEFT);
|
||||
cfg->down.def = pov_list.at(JOY_POVBACKWARD);
|
||||
cfg->right.def = pov_list.at(JOY_POVRIGHT);
|
||||
cfg->up.def = pov_list.at(JOY_POVFORWARD);
|
||||
cfg->r1.def = button_list.at(JOY_BUTTON8);
|
||||
cfg->r2.def = button_list.at(JOY_BUTTON6);
|
||||
cfg->r3.def = button_list.at(JOY_BUTTON12);
|
||||
cfg->l1.def = button_list.at(JOY_BUTTON7);
|
||||
cfg->l2.def = button_list.at(JOY_BUTTON5);
|
||||
cfg->l3.def = button_list.at(JOY_BUTTON11);
|
||||
|
||||
// Set default misc variables
|
||||
cfg->lstickdeadzone.def = 0; // between 0 and 255
|
||||
cfg->rstickdeadzone.def = 0; // between 0 and 255
|
||||
cfg->ltriggerthreshold.def = 0; // between 0 and 255
|
||||
cfg->rtriggerthreshold.def = 0; // between 0 and 255
|
||||
cfg->padsquircling.def = 8000;
|
||||
|
||||
// apply defaults
|
||||
cfg->from_default();
|
||||
}
|
||||
|
||||
bool mm_joystick_handler::Init()
|
||||
{
|
||||
if (is_init) return true;
|
||||
if (is_init)
|
||||
return true;
|
||||
|
||||
m_devices.clear();
|
||||
supportedJoysticks = joyGetNumDevs();
|
||||
m_supported_joysticks = joyGetNumDevs();
|
||||
|
||||
if (supportedJoysticks > 0)
|
||||
if (m_supported_joysticks <= 0)
|
||||
{
|
||||
LOG_NOTICE(GENERAL, "Driver supports %u joysticks", supportedJoysticks);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Driver doesn't support Joysticks");
|
||||
LOG_ERROR(GENERAL, "mmjoy: Driver doesn't support Joysticks");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < supportedJoysticks; i++)
|
||||
LOG_NOTICE(GENERAL, "mmjoy: Driver supports %u joysticks", m_supported_joysticks);
|
||||
|
||||
for (u32 i = 0; i < m_supported_joysticks; i++)
|
||||
{
|
||||
MMJOYDevice dev;
|
||||
|
||||
|
@ -93,7 +95,6 @@ bool mm_joystick_handler::Init()
|
|||
m_devices.emplace(i, dev);
|
||||
}
|
||||
|
||||
m_pad_config.load();
|
||||
is_init = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -102,7 +103,8 @@ std::vector<std::string> mm_joystick_handler::ListDevices()
|
|||
{
|
||||
std::vector<std::string> devices;
|
||||
|
||||
if (!Init()) return devices;
|
||||
if (!Init())
|
||||
return devices;
|
||||
|
||||
for (auto dev : m_devices)
|
||||
{
|
||||
|
@ -123,6 +125,13 @@ bool mm_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::s
|
|||
|
||||
std::shared_ptr<MMJOYDevice> joy_device = std::make_shared<MMJOYDevice>(m_devices.at(id));
|
||||
|
||||
int index = static_cast<int>(bindings.size());
|
||||
m_pad_configs[index].load();
|
||||
joy_device->config = &m_pad_configs[index];
|
||||
pad_config* p_profile = joy_device->config;
|
||||
if (p_profile == nullptr)
|
||||
return false;
|
||||
|
||||
auto find_key = [=](const cfg::string& name)
|
||||
{
|
||||
long key = FindKeyCode(button_list, name, false);
|
||||
|
@ -141,34 +150,34 @@ bool mm_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::s
|
|||
CELL_PAD_DEV_TYPE_STANDARD
|
||||
);
|
||||
|
||||
joy_device->trigger_left = find_key(m_pad_config.l2);
|
||||
joy_device->trigger_right = find_key(m_pad_config.r2);
|
||||
joy_device->axis_left[0] = find_key(m_pad_config.ls_left);
|
||||
joy_device->axis_left[1] = find_key(m_pad_config.ls_right);
|
||||
joy_device->axis_left[2] = find_key(m_pad_config.ls_down);
|
||||
joy_device->axis_left[3] = find_key(m_pad_config.ls_up);
|
||||
joy_device->axis_right[0] = find_key(m_pad_config.rs_left);
|
||||
joy_device->axis_right[1] = find_key(m_pad_config.rs_right);
|
||||
joy_device->axis_right[2] = find_key(m_pad_config.rs_down);
|
||||
joy_device->axis_right[3] = find_key(m_pad_config.rs_up);
|
||||
joy_device->trigger_left = find_key(p_profile->l2);
|
||||
joy_device->trigger_right = find_key(p_profile->r2);
|
||||
joy_device->axis_left[0] = find_key(p_profile->ls_left);
|
||||
joy_device->axis_left[1] = find_key(p_profile->ls_right);
|
||||
joy_device->axis_left[2] = find_key(p_profile->ls_down);
|
||||
joy_device->axis_left[3] = find_key(p_profile->ls_up);
|
||||
joy_device->axis_right[0] = find_key(p_profile->rs_left);
|
||||
joy_device->axis_right[1] = find_key(p_profile->rs_right);
|
||||
joy_device->axis_right[2] = find_key(p_profile->rs_down);
|
||||
joy_device->axis_right[3] = find_key(p_profile->rs_up);
|
||||
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_left, CELL_PAD_CTRL_L2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_right, CELL_PAD_CTRL_R2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_left, CELL_PAD_CTRL_L2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_right, CELL_PAD_CTRL_R2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, joy_device->axis_left[0], joy_device->axis_left[1]);
|
||||
|
@ -197,6 +206,7 @@ void mm_joystick_handler::ThreadProc()
|
|||
{
|
||||
m_dev = bindings[i].first;
|
||||
auto pad = bindings[i].second;
|
||||
auto profile = m_dev->config;
|
||||
status = joyGetPosEx(m_dev->device_id, &m_dev->device_info);
|
||||
|
||||
if (status != JOYERR_NOERROR)
|
||||
|
@ -232,7 +242,7 @@ void mm_joystick_handler::ThreadProc()
|
|||
TranslateButtonPress(btn.m_keyCode, btn.m_pressed, btn.m_value);
|
||||
}
|
||||
|
||||
float stick_val[4];
|
||||
s32 stick_val[4];
|
||||
|
||||
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
|
||||
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
||||
|
@ -256,13 +266,13 @@ void mm_joystick_handler::ThreadProc()
|
|||
u16 lx, ly, rx, ry;
|
||||
|
||||
// Normalize our two stick's axis based on the thresholds
|
||||
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], m_pad_config.lstickdeadzone);
|
||||
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], m_pad_config.rstickdeadzone);
|
||||
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], profile->lstickdeadzone);
|
||||
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], profile->rstickdeadzone);
|
||||
|
||||
if (m_pad_config.padsquircling != 0)
|
||||
if (profile->padsquircling != 0)
|
||||
{
|
||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, m_pad_config.padsquircling);
|
||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, m_pad_config.padsquircling);
|
||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, profile->padsquircling);
|
||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, profile->padsquircling);
|
||||
}
|
||||
|
||||
pad->m_sticks[0].m_value = lx;
|
||||
|
@ -415,26 +425,27 @@ void mm_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16&
|
|||
{
|
||||
// Update the pad button values based on their type and thresholds.
|
||||
// With this you can use axis or triggers as buttons or vice versa
|
||||
auto p_profile = m_dev->config;
|
||||
|
||||
if (keyCode == m_dev->trigger_left)
|
||||
{
|
||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.ltriggerthreshold);
|
||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.ltriggerthreshold) : 0;
|
||||
pressed = val > (ignore_threshold ? 0 : p_profile->ltriggerthreshold);
|
||||
val = pressed ? NormalizeTriggerInput(val, p_profile->ltriggerthreshold) : 0;
|
||||
}
|
||||
else if (keyCode == m_dev->trigger_right)
|
||||
{
|
||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.rtriggerthreshold);
|
||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.rtriggerthreshold) : 0;
|
||||
pressed = val > (ignore_threshold ? 0 : p_profile->rtriggerthreshold);
|
||||
val = pressed ? NormalizeTriggerInput(val, p_profile->rtriggerthreshold) : 0;
|
||||
}
|
||||
else if (std::find(m_dev->axis_left.begin(), m_dev->axis_left.end(), keyCode) != m_dev->axis_left.end())
|
||||
{
|
||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.lstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, m_pad_config.lstickdeadzone, ignore_threshold) : 0;
|
||||
pressed = val > (ignore_threshold ? 0 : p_profile->lstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, p_profile->lstickdeadzone, ignore_threshold) : 0;
|
||||
}
|
||||
else if (std::find(m_dev->axis_right.begin(), m_dev->axis_right.end(), keyCode) != m_dev->axis_right.end())
|
||||
{
|
||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.rstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, m_pad_config.rstickdeadzone, ignore_threshold) : 0;
|
||||
pressed = val > (ignore_threshold ? 0 : p_profile->rstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, p_profile->rstickdeadzone, ignore_threshold) : 0;
|
||||
}
|
||||
else // normal button (should in theory also support sensitive buttons)
|
||||
{
|
||||
|
@ -486,9 +497,9 @@ std::unordered_map<u64, u16> mm_joystick_handler::GetButtonValues(const JOYINFOE
|
|||
}
|
||||
else if (js_caps.wCaps & JOYCAPS_POV4DIR)
|
||||
{
|
||||
u64 val = js_info.dwPOV;
|
||||
int val = static_cast<int>(js_info.dwPOV);
|
||||
|
||||
auto emplacePOV = [&button_values, &val](u64 pov)
|
||||
auto emplacePOV = [&button_values, &val](int pov)
|
||||
{
|
||||
int cw = pov + 4500, ccw = pov - 4500;
|
||||
bool pressed = (val == pov) || (val == cw) || (ccw < 0 ? val == 36000 - std::abs(ccw) : val == ccw);
|
||||
|
@ -540,9 +551,7 @@ int mm_joystick_handler::GetIDByName(const std::string& name)
|
|||
for (auto dev : m_devices)
|
||||
{
|
||||
if (dev.second.device_name == name)
|
||||
{
|
||||
return dev.first;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ class mm_joystick_handler final : public PadHandlerBase
|
|||
{
|
||||
u32 device_id{ 0 };
|
||||
std::string device_name{ "" };
|
||||
pad_config* config{ nullptr };
|
||||
JOYINFOEX device_info;
|
||||
JOYCAPS device_caps;
|
||||
u64 trigger_left = 0;
|
||||
|
@ -108,6 +109,7 @@ public:
|
|||
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
|
||||
void ThreadProc() override;
|
||||
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false, std::vector<std::string> buttons = {}) override;
|
||||
void init_config(pad_config* cfg, const std::string& name) override;
|
||||
|
||||
private:
|
||||
void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override;
|
||||
|
@ -116,7 +118,7 @@ private:
|
|||
bool GetMMJOYDevice(int index, MMJOYDevice& dev);
|
||||
|
||||
bool is_init = false;
|
||||
u32 supportedJoysticks = 0;
|
||||
u32 m_supported_joysticks = 0;
|
||||
|
||||
std::vector<u64> blacklist;
|
||||
std::unordered_map<int, MMJOYDevice> m_devices;
|
||||
|
|
|
@ -30,7 +30,7 @@ void pad_thread::Init(const u32 max_connect)
|
|||
m_info.max_connect = std::min(max_connect, (u32)7); // max 7 pads
|
||||
m_info.now_connect = 0;
|
||||
|
||||
input_cfg.load();
|
||||
g_cfg_input.load();
|
||||
|
||||
std::shared_ptr<keyboard_pad_handler> keyptr;
|
||||
|
||||
|
@ -42,7 +42,7 @@ void pad_thread::Init(const u32 max_connect)
|
|||
{
|
||||
std::shared_ptr<PadHandlerBase> cur_pad_handler;
|
||||
|
||||
const auto &handler_type = input_cfg.player_input[i];
|
||||
const auto &handler_type = g_cfg_input.player[i]->handler;
|
||||
|
||||
if (handlers.count(handler_type) != 0)
|
||||
{
|
||||
|
@ -87,11 +87,11 @@ void pad_thread::Init(const u32 max_connect)
|
|||
CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_ACTUATOR,
|
||||
CELL_PAD_DEV_TYPE_STANDARD));
|
||||
|
||||
if (cur_pad_handler->bindPadToDevice(m_pads.back(), input_cfg.player_device[i]->to_string()) == false)
|
||||
if (cur_pad_handler->bindPadToDevice(m_pads.back(), g_cfg_input.player[i]->device.to_string()) == false)
|
||||
{
|
||||
//Failed to bind the device to cur_pad_handler so binds to NullPadHandler
|
||||
LOG_ERROR(GENERAL, "Failed to bind device %s to handler %s", input_cfg.player_device[i]->to_string(), handler_type.to_string());
|
||||
nullpad->bindPadToDevice(m_pads.back(), input_cfg.player_device[i]->to_string());
|
||||
LOG_ERROR(GENERAL, "Failed to bind device %s to handler %s", g_cfg_input.player[i]->device.to_string(), handler_type.to_string());
|
||||
nullpad->bindPadToDevice(m_pads.back(), g_cfg_input.player[i]->device.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <map>
|
||||
#include <thread>
|
||||
|
||||
#include "Emu/System.h"
|
||||
#include "../Utilities/types.h"
|
||||
#include "Emu/Io/PadHandler.h"
|
||||
|
||||
|
|
|
@ -10,16 +10,42 @@
|
|||
#endif
|
||||
#include "../keyboard_pad_handler.h"
|
||||
#include "../Emu/Io/Null/NullPadHandler.h"
|
||||
#include "../Emu/System.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
input_config input_cfg;
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
|
||||
inline bool CreateConfigFile(const QString& dir, const QString& name)
|
||||
{
|
||||
QString input_dir = qstr(fs::get_config_dir()) + "/InputConfigs/";
|
||||
if (!QDir().mkdir(input_dir) && !QDir().exists(input_dir))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(input_dir));
|
||||
return false;
|
||||
}
|
||||
if (!QDir().mkdir(dir) && !QDir().exists(dir))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(dir));
|
||||
return false;
|
||||
}
|
||||
|
||||
QString filename = dir + name + ".yml";
|
||||
QFile new_file(filename);
|
||||
|
||||
if (!new_file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Failed to create file %s", sstr(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
new_file.close();
|
||||
return true;
|
||||
};
|
||||
|
||||
// taken from https://stackoverflow.com/a/30818424/8353754
|
||||
// because size policies won't work as expected (see similar bugs in Qt bugtracker)
|
||||
inline void resizeComboBoxView(QComboBox* combo)
|
||||
|
@ -55,8 +81,8 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
|||
QVBoxLayout *dialog_layout = new QVBoxLayout();
|
||||
QHBoxLayout *all_players = new QHBoxLayout();
|
||||
|
||||
input_cfg.from_default();
|
||||
input_cfg.load();
|
||||
g_cfg_input.from_default();
|
||||
g_cfg_input.load();
|
||||
|
||||
for (int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
|
@ -80,20 +106,27 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
|||
co_deviceID[i]->view()->setTextElideMode(Qt::ElideNone);
|
||||
ppad_layout->addWidget(co_deviceID[i]);
|
||||
|
||||
co_profile[i] = new QComboBox();
|
||||
co_profile[i]->setEnabled(false);
|
||||
co_profile[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
|
||||
co_profile[i]->view()->setTextElideMode(Qt::ElideNone);
|
||||
ppad_layout->addWidget(co_profile[i]);
|
||||
|
||||
QHBoxLayout *button_layout = new QHBoxLayout();
|
||||
bu_config[i] = new QPushButton(tr("Config"));
|
||||
bu_new_profile[i] = new QPushButton(tr("Add Profile"));
|
||||
bu_new_profile[i]->setEnabled(false);
|
||||
bu_config[i] = new QPushButton(tr("Configure"));
|
||||
bu_config[i]->setEnabled(false);
|
||||
bu_config[i]->setFixedSize(bu_config[i]->sizeHint());
|
||||
button_layout->addSpacing(bu_config[i]->sizeHint().width()*0.50f);
|
||||
button_layout->setContentsMargins(0,0,0,0);
|
||||
button_layout->addWidget(bu_config[i]);
|
||||
button_layout->addSpacing(bu_config[i]->sizeHint().width()*0.50f);
|
||||
button_layout->addWidget(bu_new_profile[i]);
|
||||
ppad_layout->addLayout(button_layout);
|
||||
|
||||
grp_player->setLayout(ppad_layout);
|
||||
grp_player->setFixedSize(grp_player->sizeHint());
|
||||
|
||||
// fill comboboxes after setting the groupbox's size to prevent stretch
|
||||
std::vector<std::string> str_inputs = input_cfg.player_input[0].to_list();
|
||||
std::vector<std::string> str_inputs = g_cfg_input.player[0]->handler.to_list();
|
||||
for (int index = 0; index < str_inputs.size(); index++)
|
||||
{
|
||||
co_inputtype[i]->addItem(qstr(str_inputs[index]));
|
||||
|
@ -132,7 +165,7 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
|||
for (int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
// No extra loops are necessary because setCurrentText does it for us
|
||||
co_inputtype[i]->setCurrentText(qstr(input_cfg.player_input[i].to_string()));
|
||||
co_inputtype[i]->setCurrentText(qstr(g_cfg_input.player[i]->handler.to_string()));
|
||||
// Device will be empty on some rare occasions, so fill them by force
|
||||
ChangeInputType(i);
|
||||
}
|
||||
|
@ -140,18 +173,67 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
|||
|
||||
for (int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
connect(co_inputtype[i], &QComboBox::currentTextChanged, [=] { ChangeInputType(i); });
|
||||
connect(co_inputtype[i], &QComboBox::currentTextChanged, [=]
|
||||
{
|
||||
ChangeInputType(i);
|
||||
});
|
||||
connect(co_deviceID[i], &QComboBox::currentTextChanged, [=](const QString& dev)
|
||||
{
|
||||
std::string device = sstr(dev);
|
||||
if (!input_cfg.player_device[i]->from_string(device))
|
||||
if (!g_cfg_input.player[i]->device.from_string(device))
|
||||
{
|
||||
//Something went wrong
|
||||
LOG_ERROR(GENERAL, "Failed to convert device string: %s", device);
|
||||
return;
|
||||
}
|
||||
});
|
||||
connect(bu_config[i], &QAbstractButton::clicked, [=] { ClickConfigButton(i); });
|
||||
connect(co_profile[i], &QComboBox::currentTextChanged, [=](const QString& prof)
|
||||
{
|
||||
std::string profile = sstr(prof);
|
||||
if (!g_cfg_input.player[i]->profile.from_string(profile))
|
||||
{
|
||||
//Something went wrong
|
||||
LOG_ERROR(GENERAL, "Failed to convert profile string: %s", profile);
|
||||
return;
|
||||
}
|
||||
});
|
||||
connect(bu_config[i], &QAbstractButton::clicked, [=]
|
||||
{
|
||||
ClickConfigButton(i);
|
||||
});
|
||||
connect(bu_new_profile[i], &QAbstractButton::clicked, [=]
|
||||
{
|
||||
QInputDialog* dialog = new QInputDialog(this);
|
||||
dialog->setWindowTitle(tr("Choose a unique name"));
|
||||
dialog->setLabelText(tr("Profile Name: "));
|
||||
dialog->setFixedSize(500, 100);
|
||||
|
||||
while (dialog->exec() != QDialog::Rejected)
|
||||
{
|
||||
QString friendlyName = dialog->textValue();
|
||||
if (friendlyName == "")
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Name cannot be empty"));
|
||||
continue;
|
||||
}
|
||||
if (friendlyName.contains("."))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Must choose a name without '.'"));
|
||||
continue;
|
||||
}
|
||||
if (co_profile[i]->findText(friendlyName) != -1)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Please choose a non-existing name"));
|
||||
continue;
|
||||
}
|
||||
if (CreateConfigFile(qstr(PadHandlerBase::get_config_dir(g_cfg_input.player[i]->handler)), friendlyName))
|
||||
{
|
||||
co_profile[i]->addItem(friendlyName);
|
||||
co_profile[i]->setCurrentText(friendlyName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
connect(ok_button, &QPushButton::pressed, this, &gamepads_settings_dialog::SaveExit);
|
||||
connect(cancel_button, &QPushButton::pressed, this, &gamepads_settings_dialog::CancelExit);
|
||||
|
@ -167,12 +249,13 @@ void gamepads_settings_dialog::SaveExit()
|
|||
{
|
||||
if (co_deviceID[i]->currentData() == -1)
|
||||
{
|
||||
input_cfg.player_input[i].from_default();
|
||||
input_cfg.player_device[i]->from_default();
|
||||
g_cfg_input.player[i]->handler.from_default();
|
||||
g_cfg_input.player[i]->device.from_default();
|
||||
g_cfg_input.player[i]->profile.from_default();
|
||||
}
|
||||
}
|
||||
|
||||
input_cfg.save();
|
||||
g_cfg_input.save();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
@ -180,8 +263,8 @@ void gamepads_settings_dialog::SaveExit()
|
|||
void gamepads_settings_dialog::CancelExit()
|
||||
{
|
||||
//Reloads config from file or defaults
|
||||
input_cfg.from_default();
|
||||
input_cfg.load();
|
||||
g_cfg_input.from_default();
|
||||
g_cfg_input.load();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
@ -224,10 +307,11 @@ std::shared_ptr<PadHandlerBase> gamepads_settings_dialog::GetHandler(pad_handler
|
|||
void gamepads_settings_dialog::ChangeInputType(int player)
|
||||
{
|
||||
std::string handler = sstr(co_inputtype[player]->currentText());
|
||||
std::string device = input_cfg.player_device[player]->to_string();
|
||||
std::string device = g_cfg_input.player[player]->device.to_string();
|
||||
std::string profile = g_cfg_input.player[player]->profile.to_string();
|
||||
|
||||
// Change this player's current handler
|
||||
if (!input_cfg.player_input[player].from_string(handler))
|
||||
if (!g_cfg_input.player[player]->handler.from_string(handler))
|
||||
{
|
||||
//Something went wrong
|
||||
LOG_ERROR(GENERAL, "Failed to convert input string:%s", handler);
|
||||
|
@ -235,7 +319,7 @@ void gamepads_settings_dialog::ChangeInputType(int player)
|
|||
}
|
||||
|
||||
// Get this player's current handler and it's currently available devices
|
||||
std::shared_ptr<PadHandlerBase> cur_pad_handler = GetHandler(input_cfg.player_input[player]);
|
||||
std::shared_ptr<PadHandlerBase> cur_pad_handler = GetHandler(g_cfg_input.player[player]->handler);
|
||||
std::vector<std::string> list_devices = cur_pad_handler->ListDevices();
|
||||
|
||||
// Refill the device combobox with currently available devices
|
||||
|
@ -258,19 +342,60 @@ void gamepads_settings_dialog::ChangeInputType(int player)
|
|||
co_deviceID[player]->addItem(tr("No Device Detected"), -1);
|
||||
}
|
||||
|
||||
// Update view and enable configuration if possible
|
||||
bool config_enabled = device_found && cur_pad_handler->has_config();
|
||||
co_profile[player]->clear();
|
||||
|
||||
// update profile list if possible
|
||||
if (config_enabled)
|
||||
{
|
||||
QString s_profile_dir = qstr(PadHandlerBase::get_config_dir(cur_pad_handler->m_type));
|
||||
QStringList profiles = gui_settings::GetDirEntries(QDir(s_profile_dir), QStringList() << "*.yml");
|
||||
|
||||
if (profiles.isEmpty())
|
||||
{
|
||||
QString def_name = "Default Profile";
|
||||
if (!CreateConfigFile(s_profile_dir, def_name))
|
||||
{
|
||||
config_enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
co_profile[player]->addItem(def_name);
|
||||
co_profile[player]->setCurrentText(def_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& prof : profiles)
|
||||
{
|
||||
co_profile[player]->addItem(prof);
|
||||
}
|
||||
co_profile[player]->setCurrentText(qstr(profile));
|
||||
}
|
||||
}
|
||||
|
||||
if (!config_enabled)
|
||||
co_profile[player]->addItem(tr("No Profiles"));
|
||||
|
||||
// enable configuration and profile list if possible
|
||||
bu_config[player]->setEnabled(config_enabled);
|
||||
bu_new_profile[player]->setEnabled(config_enabled);
|
||||
co_profile[player]->setEnabled(config_enabled);
|
||||
|
||||
// update view
|
||||
resizeComboBoxView(co_deviceID[player]);
|
||||
bu_config[player]->setEnabled(device_found && cur_pad_handler->has_config());
|
||||
resizeComboBoxView(co_profile[player]);
|
||||
}
|
||||
|
||||
void gamepads_settings_dialog::ClickConfigButton(int player)
|
||||
{
|
||||
// Get this player's current handler and open its pad settings dialog
|
||||
std::shared_ptr<PadHandlerBase> cur_pad_handler = GetHandler(input_cfg.player_input[player]);
|
||||
std::shared_ptr<PadHandlerBase> cur_pad_handler = GetHandler(g_cfg_input.player[player]->handler);
|
||||
if (cur_pad_handler->has_config())
|
||||
{
|
||||
std::string device = sstr(co_deviceID[player]->currentText());
|
||||
pad_settings_dialog dlg(device, cur_pad_handler);
|
||||
std::string profile = sstr(co_profile[player]->currentText());
|
||||
pad_settings_dialog dlg(device, profile, cur_pad_handler);
|
||||
dlg.exec();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,52 +12,6 @@
|
|||
#include "../../Utilities/File.h"
|
||||
#include "../Emu/Io/PadHandler.h"
|
||||
|
||||
struct input_config final : cfg::node
|
||||
{
|
||||
const std::string cfg_name = fs::get_config_dir() + "/config_input.yml";
|
||||
|
||||
cfg::_enum<pad_handler> player_input[7]{
|
||||
{ this, "Player 1 Input", pad_handler::keyboard },
|
||||
{ this, "Player 2 Input", pad_handler::null },
|
||||
{ this, "Player 3 Input", pad_handler::null },
|
||||
{ this, "Player 4 Input", pad_handler::null },
|
||||
{ this, "Player 5 Input", pad_handler::null },
|
||||
{ this, "Player 6 Input", pad_handler::null },
|
||||
{ this, "Player 7 Input", pad_handler::null } };
|
||||
|
||||
cfg::string player1{ this, "Player 1 Device", "Keyboard" };
|
||||
cfg::string player2{ this, "Player 2 Device", "Default Null Device" };
|
||||
cfg::string player3{ this, "Player 3 Device", "Default Null Device" };
|
||||
cfg::string player4{ this, "Player 4 Device", "Default Null Device" };
|
||||
cfg::string player5{ this, "Player 5 Device", "Default Null Device" };
|
||||
cfg::string player6{ this, "Player 6 Device", "Default Null Device" };
|
||||
cfg::string player7{ this, "Player 7 Device", "Default Null Device" };
|
||||
|
||||
cfg::string *player_device[7]{ &player1, &player2, &player3, &player4, &player5, &player6, &player7 }; // Thanks gcc!
|
||||
|
||||
bool load()
|
||||
{
|
||||
if (fs::file cfg_file{ cfg_name, fs::read })
|
||||
{
|
||||
return from_string(cfg_file.to_string());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void save()
|
||||
{
|
||||
fs::file(cfg_name, fs::rewrite).write(to_string());
|
||||
}
|
||||
|
||||
bool exist()
|
||||
{
|
||||
return fs::is_file(cfg_name);
|
||||
}
|
||||
};
|
||||
|
||||
extern input_config input_cfg;
|
||||
|
||||
class gamepads_settings_dialog : public QDialog
|
||||
{
|
||||
const int MAX_PLAYERS = 7;
|
||||
|
@ -72,7 +26,9 @@ protected:
|
|||
protected:
|
||||
QComboBox *co_inputtype[7];
|
||||
QComboBox *co_deviceID[7];
|
||||
QComboBox *co_profile[7];
|
||||
QPushButton *bu_config[7];
|
||||
QPushButton *bu_new_profile[7];
|
||||
|
||||
public:
|
||||
gamepads_settings_dialog(QWidget* parent);
|
||||
|
|
|
@ -7,13 +7,18 @@
|
|||
#include <QKeyEvent>
|
||||
#include <QTimer>
|
||||
#include <QThread>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rpcs3_version.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include <QGuiApplication>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#endif
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
|
@ -145,12 +150,28 @@ void gs_frame::show()
|
|||
});
|
||||
}
|
||||
|
||||
void* gs_frame::handle() const
|
||||
display_handle_t gs_frame::handle() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (HWND) this->winId();
|
||||
#else
|
||||
return (void *)this->winId();
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
|
||||
struct wl_display *wl_dpy = static_cast<struct wl_display *>(
|
||||
native->nativeResourceForWindow("display", NULL));
|
||||
struct wl_surface *wl_surf = static_cast<struct wl_surface *>(
|
||||
native->nativeResourceForWindow("surface", (QWindow *)this));
|
||||
if (wl_dpy != nullptr && wl_surf != nullptr)
|
||||
{
|
||||
return std::make_pair(wl_dpy, wl_surf);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
return std::make_pair(XOpenDisplay(0), (unsigned long)(this->winId()));
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ protected:
|
|||
void show() override;
|
||||
void mouseDoubleClickEvent(QMouseEvent* ev) override;
|
||||
|
||||
void* handle() const override;
|
||||
display_handle_t handle() const override;
|
||||
|
||||
void flip(draw_context_t context, bool skip_frame=false) override;
|
||||
int client_width() override;
|
||||
|
|
|
@ -321,6 +321,17 @@ QStringList gui_settings::GetConfigEntries()
|
|||
return res;
|
||||
}
|
||||
|
||||
QStringList gui_settings::GetDirEntries(const QDir& dir, const QStringList& nameFilters)
|
||||
{
|
||||
QFileInfoList entries = dir.entryInfoList(nameFilters, QDir::Files);
|
||||
QStringList res;
|
||||
for (const QFileInfo &entry : entries)
|
||||
{
|
||||
res.append(entry.baseName());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void gui_settings::BackupSettingsToTarget(const QString& friendlyName)
|
||||
{
|
||||
QSettings target(ComputeSettingsDir() + friendlyName + ".ini", QSettings::Format::IniFormat);
|
||||
|
|
|
@ -231,6 +231,7 @@ public:
|
|||
bool GetGamelistColVisibility(int col);
|
||||
QColor GetCustomColor(int col);
|
||||
QStringList GetConfigEntries();
|
||||
static QStringList GetDirEntries(const QDir& dir, const QStringList& nameFilters);
|
||||
QString GetCurrentStylesheetPath();
|
||||
QStringList GetStylesheetEntries();
|
||||
QStringList GetGameListCategoryFilters();
|
||||
|
|
|
@ -13,11 +13,9 @@
|
|||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
|
||||
pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_ptr<PadHandlerBase> handler, QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::pad_settings_dialog), m_handler_cfg(handler->GetConfig()), m_device_name(device), m_handler(handler)
|
||||
pad_settings_dialog::pad_settings_dialog(const std::string& device, const std::string& profile, std::shared_ptr<PadHandlerBase> handler, QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::pad_settings_dialog), m_device_name(device), m_handler(handler), m_handler_type(handler->m_type)
|
||||
{
|
||||
m_handler_cfg->load();
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
@ -28,37 +26,47 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
|
|||
m_padButtons = new QButtonGroup(this);
|
||||
m_palette = ui->b_left->palette(); // save normal palette
|
||||
|
||||
ui->chb_vibration_large->setChecked((bool)m_handler_cfg->enable_vibration_motor_large);
|
||||
ui->chb_vibration_small->setChecked((bool)m_handler_cfg->enable_vibration_motor_small);
|
||||
ui->chb_vibration_switch->setChecked((bool)m_handler_cfg->switch_vibration_motors);
|
||||
std::string cfg_name = PadHandlerBase::get_config_dir(m_handler_type) + profile + ".yml";
|
||||
|
||||
// Adjust to the different pad handlers
|
||||
if (m_handler_cfg->cfg_type == "keyboard")
|
||||
if (m_handler_type == pad_handler::keyboard)
|
||||
{
|
||||
setWindowTitle(tr("Configure Keyboard"));
|
||||
m_handler_type = handler_type::handler_type_keyboard;
|
||||
ui->b_blacklist->setEnabled(false);
|
||||
((keyboard_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||
}
|
||||
else if (m_handler_cfg->cfg_type == "xinput")
|
||||
{
|
||||
setWindowTitle(tr("Configure XInput"));
|
||||
m_handler_type = handler_type::handler_type_xinput;
|
||||
}
|
||||
else if (m_handler_cfg->cfg_type == "ds4")
|
||||
else if (m_handler_type == pad_handler::ds4)
|
||||
{
|
||||
setWindowTitle(tr("Configure DS4"));
|
||||
m_handler_type = handler_type::handler_type_ds4;
|
||||
((ds4_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||
}
|
||||
else if (m_handler_cfg->cfg_type == "mmjoystick")
|
||||
#ifdef _MSC_VER
|
||||
else if (m_handler_type == pad_handler::xinput)
|
||||
{
|
||||
setWindowTitle(tr("Configure XInput"));
|
||||
((xinput_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||
}
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
else if (m_handler_type == pad_handler::mm)
|
||||
{
|
||||
setWindowTitle(tr("Configure MMJoystick"));
|
||||
m_handler_type = handler_type::handler_type_mmjoy;
|
||||
((mm_joystick_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||
}
|
||||
else if (m_handler_cfg->cfg_type == "evdev")
|
||||
#endif
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
else if (m_handler_type == pad_handler::evdev)
|
||||
{
|
||||
setWindowTitle(tr("Configure evdev"));
|
||||
m_handler_type = handler_type::handler_type_evdev;
|
||||
((evdev_joystick_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_handler_cfg.load();
|
||||
|
||||
ui->chb_vibration_large->setChecked((bool)m_handler_cfg.enable_vibration_motor_large);
|
||||
ui->chb_vibration_small->setChecked((bool)m_handler_cfg.enable_vibration_motor_small);
|
||||
ui->chb_vibration_switch->setChecked((bool)m_handler_cfg.switch_vibration_motors);
|
||||
|
||||
// Enable Button Remapping
|
||||
if (m_handler->has_config())
|
||||
|
@ -85,7 +93,7 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
|
|||
|
||||
if (val <= 0) return;
|
||||
|
||||
LOG_NOTICE(HLE, "GetNextButtonPress: %s button %s pressed with value %d", m_handler_cfg->cfg_type, name, val);
|
||||
LOG_NOTICE(HLE, "GetNextButtonPress: %s button %s pressed with value %d", m_handler_type, name, val);
|
||||
if (m_button_id > button_ids::id_pad_begin && m_button_id < button_ids::id_pad_end)
|
||||
{
|
||||
m_cfg_entries[m_button_id].key = name;
|
||||
|
@ -185,14 +193,14 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
|
|||
};
|
||||
|
||||
// Enable Trigger Thresholds
|
||||
initSlider(ui->slider_trigger_left, m_handler_cfg->ltriggerthreshold, 0, m_handler->trigger_max);
|
||||
initSlider(ui->slider_trigger_right, m_handler_cfg->rtriggerthreshold, 0, m_handler->trigger_max);
|
||||
initSlider(ui->slider_trigger_left, m_handler_cfg.ltriggerthreshold, 0, m_handler->trigger_max);
|
||||
initSlider(ui->slider_trigger_right, m_handler_cfg.rtriggerthreshold, 0, m_handler->trigger_max);
|
||||
ui->preview_trigger_left->setRange(0, m_handler->trigger_max);
|
||||
ui->preview_trigger_right->setRange(0, m_handler->trigger_max);
|
||||
|
||||
// Enable Stick Deadzones
|
||||
initSlider(ui->slider_stick_left, m_handler_cfg->lstickdeadzone, 0, m_handler->thumb_max);
|
||||
initSlider(ui->slider_stick_right, m_handler_cfg->rstickdeadzone, 0, m_handler->thumb_max);
|
||||
initSlider(ui->slider_stick_left, m_handler_cfg.lstickdeadzone, 0, m_handler->thumb_max);
|
||||
initSlider(ui->slider_stick_right, m_handler_cfg.rstickdeadzone, 0, m_handler->thumb_max);
|
||||
|
||||
RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->sizeHint().width(), lx, ly);
|
||||
connect(ui->slider_stick_left, &QSlider::valueChanged, [&](int value)
|
||||
|
@ -224,37 +232,37 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
|
|||
button->installEventFilter(this);
|
||||
};
|
||||
|
||||
insertButton(button_ids::id_pad_lstick_left, ui->b_lstick_left, &m_handler_cfg->ls_left);
|
||||
insertButton(button_ids::id_pad_lstick_down, ui->b_lstick_down, &m_handler_cfg->ls_down);
|
||||
insertButton(button_ids::id_pad_lstick_right, ui->b_lstick_right, &m_handler_cfg->ls_right);
|
||||
insertButton(button_ids::id_pad_lstick_up, ui->b_lstick_up, &m_handler_cfg->ls_up);
|
||||
insertButton(button_ids::id_pad_lstick_left, ui->b_lstick_left, &m_handler_cfg.ls_left);
|
||||
insertButton(button_ids::id_pad_lstick_down, ui->b_lstick_down, &m_handler_cfg.ls_down);
|
||||
insertButton(button_ids::id_pad_lstick_right, ui->b_lstick_right, &m_handler_cfg.ls_right);
|
||||
insertButton(button_ids::id_pad_lstick_up, ui->b_lstick_up, &m_handler_cfg.ls_up);
|
||||
|
||||
insertButton(button_ids::id_pad_left, ui->b_left, &m_handler_cfg->left);
|
||||
insertButton(button_ids::id_pad_down, ui->b_down, &m_handler_cfg->down);
|
||||
insertButton(button_ids::id_pad_right, ui->b_right, &m_handler_cfg->right);
|
||||
insertButton(button_ids::id_pad_up, ui->b_up, &m_handler_cfg->up);
|
||||
insertButton(button_ids::id_pad_left, ui->b_left, &m_handler_cfg.left);
|
||||
insertButton(button_ids::id_pad_down, ui->b_down, &m_handler_cfg.down);
|
||||
insertButton(button_ids::id_pad_right, ui->b_right, &m_handler_cfg.right);
|
||||
insertButton(button_ids::id_pad_up, ui->b_up, &m_handler_cfg.up);
|
||||
|
||||
insertButton(button_ids::id_pad_l1, ui->b_shift_l1, &m_handler_cfg->l1);
|
||||
insertButton(button_ids::id_pad_l2, ui->b_shift_l2, &m_handler_cfg->l2);
|
||||
insertButton(button_ids::id_pad_l3, ui->b_shift_l3, &m_handler_cfg->l3);
|
||||
insertButton(button_ids::id_pad_l1, ui->b_shift_l1, &m_handler_cfg.l1);
|
||||
insertButton(button_ids::id_pad_l2, ui->b_shift_l2, &m_handler_cfg.l2);
|
||||
insertButton(button_ids::id_pad_l3, ui->b_shift_l3, &m_handler_cfg.l3);
|
||||
|
||||
insertButton(button_ids::id_pad_start, ui->b_start, &m_handler_cfg->start);
|
||||
insertButton(button_ids::id_pad_select, ui->b_select, &m_handler_cfg->select);
|
||||
insertButton(button_ids::id_pad_ps, ui->b_ps, &m_handler_cfg->ps);
|
||||
insertButton(button_ids::id_pad_start, ui->b_start, &m_handler_cfg.start);
|
||||
insertButton(button_ids::id_pad_select, ui->b_select, &m_handler_cfg.select);
|
||||
insertButton(button_ids::id_pad_ps, ui->b_ps, &m_handler_cfg.ps);
|
||||
|
||||
insertButton(button_ids::id_pad_r1, ui->b_shift_r1, &m_handler_cfg->r1);
|
||||
insertButton(button_ids::id_pad_r2, ui->b_shift_r2, &m_handler_cfg->r2);
|
||||
insertButton(button_ids::id_pad_r3, ui->b_shift_r3, &m_handler_cfg->r3);
|
||||
insertButton(button_ids::id_pad_r1, ui->b_shift_r1, &m_handler_cfg.r1);
|
||||
insertButton(button_ids::id_pad_r2, ui->b_shift_r2, &m_handler_cfg.r2);
|
||||
insertButton(button_ids::id_pad_r3, ui->b_shift_r3, &m_handler_cfg.r3);
|
||||
|
||||
insertButton(button_ids::id_pad_square, ui->b_square, &m_handler_cfg->square);
|
||||
insertButton(button_ids::id_pad_cross, ui->b_cross, &m_handler_cfg->cross);
|
||||
insertButton(button_ids::id_pad_circle, ui->b_circle, &m_handler_cfg->circle);
|
||||
insertButton(button_ids::id_pad_triangle, ui->b_triangle, &m_handler_cfg->triangle);
|
||||
insertButton(button_ids::id_pad_square, ui->b_square, &m_handler_cfg.square);
|
||||
insertButton(button_ids::id_pad_cross, ui->b_cross, &m_handler_cfg.cross);
|
||||
insertButton(button_ids::id_pad_circle, ui->b_circle, &m_handler_cfg.circle);
|
||||
insertButton(button_ids::id_pad_triangle, ui->b_triangle, &m_handler_cfg.triangle);
|
||||
|
||||
insertButton(button_ids::id_pad_rstick_left, ui->b_rstick_left, &m_handler_cfg->rs_left);
|
||||
insertButton(button_ids::id_pad_rstick_down, ui->b_rstick_down, &m_handler_cfg->rs_down);
|
||||
insertButton(button_ids::id_pad_rstick_right, ui->b_rstick_right, &m_handler_cfg->rs_right);
|
||||
insertButton(button_ids::id_pad_rstick_up, ui->b_rstick_up, &m_handler_cfg->rs_up);
|
||||
insertButton(button_ids::id_pad_rstick_left, ui->b_rstick_left, &m_handler_cfg.rs_left);
|
||||
insertButton(button_ids::id_pad_rstick_down, ui->b_rstick_down, &m_handler_cfg.rs_down);
|
||||
insertButton(button_ids::id_pad_rstick_right, ui->b_rstick_right, &m_handler_cfg.rs_right);
|
||||
insertButton(button_ids::id_pad_rstick_up, ui->b_rstick_up, &m_handler_cfg.rs_up);
|
||||
|
||||
m_padButtons->addButton(ui->b_reset, button_ids::id_reset_parameters);
|
||||
m_padButtons->addButton(ui->b_blacklist, button_ids::id_blacklist);
|
||||
|
@ -345,7 +353,7 @@ void pad_settings_dialog::RepaintPreviewLabel(QLabel* l, int dz, int w, int x, i
|
|||
|
||||
void pad_settings_dialog::keyPressEvent(QKeyEvent *keyEvent)
|
||||
{
|
||||
if (m_handler_type != handler_type::handler_type_keyboard)
|
||||
if (m_handler_type != pad_handler::keyboard)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -370,7 +378,7 @@ void pad_settings_dialog::keyPressEvent(QKeyEvent *keyEvent)
|
|||
|
||||
void pad_settings_dialog::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
if (m_handler_type != handler_type::handler_type_keyboard)
|
||||
if (m_handler_type != pad_handler::keyboard)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -407,17 +415,17 @@ void pad_settings_dialog::UpdateLabel(bool is_reset)
|
|||
{
|
||||
if (m_handler->has_rumble())
|
||||
{
|
||||
ui->chb_vibration_large->setChecked((bool)m_handler_cfg->enable_vibration_motor_large);
|
||||
ui->chb_vibration_small->setChecked((bool)m_handler_cfg->enable_vibration_motor_small);
|
||||
ui->chb_vibration_switch->setChecked((bool)m_handler_cfg->switch_vibration_motors);
|
||||
ui->chb_vibration_large->setChecked((bool)m_handler_cfg.enable_vibration_motor_large);
|
||||
ui->chb_vibration_small->setChecked((bool)m_handler_cfg.enable_vibration_motor_small);
|
||||
ui->chb_vibration_switch->setChecked((bool)m_handler_cfg.switch_vibration_motors);
|
||||
}
|
||||
|
||||
if (m_handler->has_deadzones())
|
||||
{
|
||||
ui->slider_trigger_left->setValue(m_handler_cfg->ltriggerthreshold);
|
||||
ui->slider_trigger_right->setValue(m_handler_cfg->rtriggerthreshold);
|
||||
ui->slider_stick_left->setValue(m_handler_cfg->lstickdeadzone);
|
||||
ui->slider_stick_right->setValue(m_handler_cfg->rstickdeadzone);
|
||||
ui->slider_trigger_left->setValue(m_handler_cfg.ltriggerthreshold);
|
||||
ui->slider_trigger_right->setValue(m_handler_cfg.rtriggerthreshold);
|
||||
ui->slider_stick_left->setValue(m_handler_cfg.lstickdeadzone);
|
||||
ui->slider_stick_right->setValue(m_handler_cfg.rstickdeadzone);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,20 +458,20 @@ void pad_settings_dialog::SaveConfig()
|
|||
|
||||
if (m_handler->has_rumble())
|
||||
{
|
||||
m_handler_cfg->enable_vibration_motor_large.set(ui->chb_vibration_large->isChecked());
|
||||
m_handler_cfg->enable_vibration_motor_small.set(ui->chb_vibration_small->isChecked());
|
||||
m_handler_cfg->switch_vibration_motors.set(ui->chb_vibration_switch->isChecked());
|
||||
m_handler_cfg.enable_vibration_motor_large.set(ui->chb_vibration_large->isChecked());
|
||||
m_handler_cfg.enable_vibration_motor_small.set(ui->chb_vibration_small->isChecked());
|
||||
m_handler_cfg.switch_vibration_motors.set(ui->chb_vibration_switch->isChecked());
|
||||
}
|
||||
|
||||
if (m_handler->has_deadzones())
|
||||
{
|
||||
m_handler_cfg->ltriggerthreshold.set(ui->slider_trigger_left->value());
|
||||
m_handler_cfg->rtriggerthreshold.set(ui->slider_trigger_right->value());
|
||||
m_handler_cfg->lstickdeadzone.set(ui->slider_stick_left->value());
|
||||
m_handler_cfg->rstickdeadzone.set(ui->slider_stick_right->value());
|
||||
m_handler_cfg.ltriggerthreshold.set(ui->slider_trigger_left->value());
|
||||
m_handler_cfg.rtriggerthreshold.set(ui->slider_trigger_right->value());
|
||||
m_handler_cfg.lstickdeadzone.set(ui->slider_stick_left->value());
|
||||
m_handler_cfg.rstickdeadzone.set(ui->slider_stick_right->value());
|
||||
}
|
||||
|
||||
m_handler_cfg->save();
|
||||
m_handler_cfg.save();
|
||||
}
|
||||
|
||||
void pad_settings_dialog::OnPadButtonClicked(int id)
|
||||
|
@ -476,7 +484,7 @@ void pad_settings_dialog::OnPadButtonClicked(int id)
|
|||
return;
|
||||
case button_ids::id_reset_parameters:
|
||||
ReactivateButtons();
|
||||
m_handler_cfg->from_default();
|
||||
m_handler_cfg.from_default();
|
||||
UpdateLabel(true);
|
||||
return;
|
||||
case button_ids::id_blacklist:
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
#ifdef _WIN32
|
||||
#include "xinput_pad_handler.h"
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#include "mm_joystick_handler.h"
|
||||
#endif
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
#include "evdev_joystick_handler.h"
|
||||
#endif
|
||||
#include "ds4_pad_handler.h"
|
||||
|
||||
namespace Ui
|
||||
|
@ -72,15 +78,6 @@ class pad_settings_dialog : public QDialog
|
|||
id_cancel
|
||||
};
|
||||
|
||||
enum handler_type
|
||||
{
|
||||
handler_type_keyboard,
|
||||
handler_type_xinput,
|
||||
handler_type_ds4,
|
||||
handler_type_mmjoy,
|
||||
handler_type_evdev
|
||||
};
|
||||
|
||||
struct pad_button
|
||||
{
|
||||
cfg::string* cfg_name;
|
||||
|
@ -109,9 +106,9 @@ private:
|
|||
QPalette m_palette;
|
||||
|
||||
// Pad Handlers
|
||||
pad_handler m_handler_type;
|
||||
std::shared_ptr<PadHandlerBase> m_handler;
|
||||
handler_type m_handler_type;
|
||||
pad_config* m_handler_cfg;
|
||||
pad_config m_handler_cfg;
|
||||
std::string m_device_name;
|
||||
|
||||
// Remap Timer
|
||||
|
@ -129,7 +126,7 @@ private:
|
|||
void RepaintPreviewLabel(QLabel* l, int dz, int w, int x, int y);
|
||||
|
||||
public:
|
||||
explicit pad_settings_dialog(const std::string& device, std::shared_ptr<PadHandlerBase> handler, QWidget *parent = nullptr);
|
||||
explicit pad_settings_dialog(const std::string& device, const std::string& profile, std::shared_ptr<PadHandlerBase> handler, QWidget *parent = nullptr);
|
||||
~pad_settings_dialog();
|
||||
|
||||
/** Handle keyboard handler input */
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
|
||||
#ifdef _MSC_VER
|
||||
#include "xinput_pad_handler.h"
|
||||
#include "rpcs3qt/pad_settings_dialog.h"
|
||||
|
||||
xinput_pad_handler::xinput_pad_handler() :
|
||||
library(nullptr), xinputGetState(nullptr), xinputEnable(nullptr),
|
||||
xinputSetState(nullptr), xinputGetBatteryInformation(nullptr), is_init(false)
|
||||
xinput_pad_handler::xinput_pad_handler() : PadHandlerBase(pad_handler::xinput)
|
||||
{
|
||||
init_configs();
|
||||
|
||||
// Define border values
|
||||
thumb_min = -32768;
|
||||
thumb_max = 32767;
|
||||
|
@ -15,47 +14,6 @@ xinput_pad_handler::xinput_pad_handler() :
|
|||
vibration_min = 0;
|
||||
vibration_max = 65535;
|
||||
|
||||
// Set this handler's type and save location
|
||||
m_pad_config.cfg_type = "xinput";
|
||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_xinput.yml";
|
||||
|
||||
// Set default button mapping
|
||||
m_pad_config.ls_left.def = button_list.at(XInputKeyCodes::LSXNeg);
|
||||
m_pad_config.ls_down.def = button_list.at(XInputKeyCodes::LSYNeg);
|
||||
m_pad_config.ls_right.def = button_list.at(XInputKeyCodes::LSXPos);
|
||||
m_pad_config.ls_up.def = button_list.at(XInputKeyCodes::LSYPos);
|
||||
m_pad_config.rs_left.def = button_list.at(XInputKeyCodes::RSXNeg);
|
||||
m_pad_config.rs_down.def = button_list.at(XInputKeyCodes::RSYNeg);
|
||||
m_pad_config.rs_right.def = button_list.at(XInputKeyCodes::RSXPos);
|
||||
m_pad_config.rs_up.def = button_list.at(XInputKeyCodes::RSYPos);
|
||||
m_pad_config.start.def = button_list.at(XInputKeyCodes::Start);
|
||||
m_pad_config.select.def = button_list.at(XInputKeyCodes::Back);
|
||||
m_pad_config.ps.def = button_list.at(XInputKeyCodes::Guide);
|
||||
m_pad_config.square.def = button_list.at(XInputKeyCodes::X);
|
||||
m_pad_config.cross.def = button_list.at(XInputKeyCodes::A);
|
||||
m_pad_config.circle.def = button_list.at(XInputKeyCodes::B);
|
||||
m_pad_config.triangle.def = button_list.at(XInputKeyCodes::Y);
|
||||
m_pad_config.left.def = button_list.at(XInputKeyCodes::Left);
|
||||
m_pad_config.down.def = button_list.at(XInputKeyCodes::Down);
|
||||
m_pad_config.right.def = button_list.at(XInputKeyCodes::Right);
|
||||
m_pad_config.up.def = button_list.at(XInputKeyCodes::Up);
|
||||
m_pad_config.r1.def = button_list.at(XInputKeyCodes::RB);
|
||||
m_pad_config.r2.def = button_list.at(XInputKeyCodes::RT);
|
||||
m_pad_config.r3.def = button_list.at(XInputKeyCodes::RS);
|
||||
m_pad_config.l1.def = button_list.at(XInputKeyCodes::LB);
|
||||
m_pad_config.l2.def = button_list.at(XInputKeyCodes::LT);
|
||||
m_pad_config.l3.def = button_list.at(XInputKeyCodes::LS);
|
||||
|
||||
// Set default misc variables
|
||||
m_pad_config.lstickdeadzone.def = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE; // between 0 and 32767
|
||||
m_pad_config.rstickdeadzone.def = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE; // between 0 and 32767
|
||||
m_pad_config.ltriggerthreshold.def = XINPUT_GAMEPAD_TRIGGER_THRESHOLD; // between 0 and 255
|
||||
m_pad_config.rtriggerthreshold.def = XINPUT_GAMEPAD_TRIGGER_THRESHOLD; // between 0 and 255
|
||||
m_pad_config.padsquircling.def = 8000;
|
||||
|
||||
// apply defaults
|
||||
m_pad_config.from_default();
|
||||
|
||||
// set capabilities
|
||||
b_has_config = true;
|
||||
b_has_rumble = true;
|
||||
|
@ -70,6 +28,49 @@ xinput_pad_handler::~xinput_pad_handler()
|
|||
Close();
|
||||
}
|
||||
|
||||
void xinput_pad_handler::init_config(pad_config* cfg, const std::string& name)
|
||||
{
|
||||
// Set this profile's save location
|
||||
cfg->cfg_name = name;
|
||||
|
||||
// Set default button mapping
|
||||
cfg->ls_left.def = button_list.at(XInputKeyCodes::LSXNeg);
|
||||
cfg->ls_down.def = button_list.at(XInputKeyCodes::LSYNeg);
|
||||
cfg->ls_right.def = button_list.at(XInputKeyCodes::LSXPos);
|
||||
cfg->ls_up.def = button_list.at(XInputKeyCodes::LSYPos);
|
||||
cfg->rs_left.def = button_list.at(XInputKeyCodes::RSXNeg);
|
||||
cfg->rs_down.def = button_list.at(XInputKeyCodes::RSYNeg);
|
||||
cfg->rs_right.def = button_list.at(XInputKeyCodes::RSXPos);
|
||||
cfg->rs_up.def = button_list.at(XInputKeyCodes::RSYPos);
|
||||
cfg->start.def = button_list.at(XInputKeyCodes::Start);
|
||||
cfg->select.def = button_list.at(XInputKeyCodes::Back);
|
||||
cfg->ps.def = button_list.at(XInputKeyCodes::Guide);
|
||||
cfg->square.def = button_list.at(XInputKeyCodes::X);
|
||||
cfg->cross.def = button_list.at(XInputKeyCodes::A);
|
||||
cfg->circle.def = button_list.at(XInputKeyCodes::B);
|
||||
cfg->triangle.def = button_list.at(XInputKeyCodes::Y);
|
||||
cfg->left.def = button_list.at(XInputKeyCodes::Left);
|
||||
cfg->down.def = button_list.at(XInputKeyCodes::Down);
|
||||
cfg->right.def = button_list.at(XInputKeyCodes::Right);
|
||||
cfg->up.def = button_list.at(XInputKeyCodes::Up);
|
||||
cfg->r1.def = button_list.at(XInputKeyCodes::RB);
|
||||
cfg->r2.def = button_list.at(XInputKeyCodes::RT);
|
||||
cfg->r3.def = button_list.at(XInputKeyCodes::RS);
|
||||
cfg->l1.def = button_list.at(XInputKeyCodes::LB);
|
||||
cfg->l2.def = button_list.at(XInputKeyCodes::LT);
|
||||
cfg->l3.def = button_list.at(XInputKeyCodes::LS);
|
||||
|
||||
// Set default misc variables
|
||||
cfg->lstickdeadzone.def = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE; // between 0 and 32767
|
||||
cfg->rstickdeadzone.def = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE; // between 0 and 32767
|
||||
cfg->ltriggerthreshold.def = XINPUT_GAMEPAD_TRIGGER_THRESHOLD; // between 0 and 255
|
||||
cfg->rtriggerthreshold.def = XINPUT_GAMEPAD_TRIGGER_THRESHOLD; // between 0 and 255
|
||||
cfg->padsquircling.def = 8000;
|
||||
|
||||
// apply defaults
|
||||
cfg->from_default();
|
||||
}
|
||||
|
||||
void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist, std::vector<std::string> buttons)
|
||||
{
|
||||
if (get_blacklist)
|
||||
|
@ -152,29 +153,30 @@ void xinput_pad_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& v
|
|||
{
|
||||
// Update the pad button values based on their type and thresholds.
|
||||
// With this you can use axis or triggers as buttons or vice versa
|
||||
auto p_profile = m_dev->config;
|
||||
switch (keyCode)
|
||||
{
|
||||
case XInputKeyCodes::LT:
|
||||
pressed = val > m_pad_config.ltriggerthreshold;
|
||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.ltriggerthreshold) : 0;
|
||||
pressed = val > p_profile->ltriggerthreshold;
|
||||
val = pressed ? NormalizeTriggerInput(val, p_profile->ltriggerthreshold) : 0;
|
||||
break;
|
||||
case XInputKeyCodes::RT:
|
||||
pressed = val > m_pad_config.rtriggerthreshold;
|
||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.rtriggerthreshold) : 0;
|
||||
pressed = val > p_profile->rtriggerthreshold;
|
||||
val = pressed ? NormalizeTriggerInput(val, p_profile->rtriggerthreshold) : 0;
|
||||
break;
|
||||
case XInputKeyCodes::LSXNeg:
|
||||
case XInputKeyCodes::LSXPos:
|
||||
case XInputKeyCodes::LSYPos:
|
||||
case XInputKeyCodes::LSYNeg:
|
||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.lstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, m_pad_config.lstickdeadzone, ignore_threshold) : 0;
|
||||
pressed = val > (ignore_threshold ? 0 : p_profile->lstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, p_profile->lstickdeadzone, ignore_threshold) : 0;
|
||||
break;
|
||||
case XInputKeyCodes::RSXNeg:
|
||||
case XInputKeyCodes::RSXPos:
|
||||
case XInputKeyCodes::RSYPos:
|
||||
case XInputKeyCodes::RSYNeg:
|
||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.rstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, m_pad_config.rstickdeadzone, ignore_threshold) : 0;
|
||||
pressed = val > (ignore_threshold ? 0 : p_profile->rstickdeadzone);
|
||||
val = pressed ? NormalizeStickInput(val, p_profile->rstickdeadzone, ignore_threshold) : 0;
|
||||
break;
|
||||
default: // normal button (should in theory also support sensitive buttons)
|
||||
pressed = val > 0;
|
||||
|
@ -293,10 +295,6 @@ bool xinput_pad_handler::Init()
|
|||
if (!is_init)
|
||||
return false;
|
||||
|
||||
m_pad_config.load();
|
||||
if (!m_pad_config.exist())
|
||||
m_pad_config.save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -316,8 +314,9 @@ void xinput_pad_handler::ThreadProc()
|
|||
{
|
||||
for (auto &bind : bindings)
|
||||
{
|
||||
auto device = bind.first;
|
||||
auto padnum = device->deviceNumber;
|
||||
m_dev = bind.first;
|
||||
auto padnum = m_dev->deviceNumber;
|
||||
auto profile = m_dev->config;
|
||||
auto pad = bind.second;
|
||||
|
||||
result = (*xinputGetState)(padnum, &state);
|
||||
|
@ -333,7 +332,7 @@ void xinput_pad_handler::ThreadProc()
|
|||
last_connection_status[padnum] = false;
|
||||
connected--;
|
||||
}
|
||||
return;
|
||||
continue;
|
||||
|
||||
case ERROR_SUCCESS:
|
||||
if (last_connection_status[padnum] == false)
|
||||
|
@ -364,7 +363,7 @@ void xinput_pad_handler::ThreadProc()
|
|||
}
|
||||
|
||||
// used to get the absolute value of an axis
|
||||
float stick_val[4];
|
||||
s32 stick_val[4];
|
||||
|
||||
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
|
||||
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
||||
|
@ -388,13 +387,13 @@ void xinput_pad_handler::ThreadProc()
|
|||
u16 lx, ly, rx, ry;
|
||||
|
||||
// Normalize our two stick's axis based on the thresholds
|
||||
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], m_pad_config.lstickdeadzone);
|
||||
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], m_pad_config.rstickdeadzone);
|
||||
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], profile->lstickdeadzone);
|
||||
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], profile->rstickdeadzone);
|
||||
|
||||
if (m_pad_config.padsquircling != 0)
|
||||
if (profile->padsquircling != 0)
|
||||
{
|
||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, m_pad_config.padsquircling);
|
||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, m_pad_config.padsquircling);
|
||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, profile->padsquircling);
|
||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, profile->padsquircling);
|
||||
}
|
||||
|
||||
pad->m_sticks[0].m_value = lx;
|
||||
|
@ -410,19 +409,19 @@ void xinput_pad_handler::ThreadProc()
|
|||
|
||||
// The left motor is the low-frequency rumble motor. The right motor is the high-frequency rumble motor.
|
||||
// The two motors are not the same, and they create different vibration effects. Values range between 0 to 65535.
|
||||
int idx_l = m_pad_config.switch_vibration_motors ? 1 : 0;
|
||||
int idx_s = m_pad_config.switch_vibration_motors ? 0 : 1;
|
||||
int idx_l = profile->switch_vibration_motors ? 1 : 0;
|
||||
int idx_s = profile->switch_vibration_motors ? 0 : 1;
|
||||
|
||||
int speed_large = m_pad_config.enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value * 257 : vibration_min;
|
||||
int speed_small = m_pad_config.enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value * 257 : vibration_min;
|
||||
int speed_large = profile->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value * 257 : vibration_min;
|
||||
int speed_small = profile->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value * 257 : vibration_min;
|
||||
|
||||
device->newVibrateData = device->newVibrateData || device->largeVibrate != speed_large || device->smallVibrate != speed_small;
|
||||
m_dev->newVibrateData = m_dev->newVibrateData || m_dev->largeVibrate != speed_large || m_dev->smallVibrate != speed_small;
|
||||
|
||||
device->largeVibrate = speed_large;
|
||||
device->smallVibrate = speed_small;
|
||||
m_dev->largeVibrate = speed_large;
|
||||
m_dev->smallVibrate = speed_small;
|
||||
|
||||
// XBox One Controller can't handle faster vibration updates than ~10ms. Elite is even worse. So I'll use 20ms to be on the safe side. No lag was noticable.
|
||||
if (device->newVibrateData && (clock() - device->last_vibration > 20))
|
||||
if (m_dev->newVibrateData && (clock() - m_dev->last_vibration > 20))
|
||||
{
|
||||
XINPUT_VIBRATION vibrate;
|
||||
vibrate.wLeftMotorSpeed = speed_large;
|
||||
|
@ -430,8 +429,8 @@ void xinput_pad_handler::ThreadProc()
|
|||
|
||||
if ((*xinputSetState)(padnum, &vibrate) == ERROR_SUCCESS)
|
||||
{
|
||||
device->newVibrateData = false;
|
||||
device->last_vibration = clock();
|
||||
m_dev->newVibrateData = false;
|
||||
m_dev->last_vibration = clock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,10 +463,15 @@ bool xinput_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::st
|
|||
if (device_number < 0)
|
||||
return false;
|
||||
|
||||
std::shared_ptr<XInputDevice> device_id = std::make_shared<XInputDevice>();
|
||||
device_id->deviceNumber = static_cast<u32>(device_number);
|
||||
std::shared_ptr<XInputDevice> x_device = std::make_shared<XInputDevice>();
|
||||
x_device->deviceNumber = static_cast<u32>(device_number);
|
||||
|
||||
m_pad_config.load();
|
||||
int index = static_cast<int>(bindings.size());
|
||||
m_pad_configs[index].load();
|
||||
x_device->config = &m_pad_configs[index];
|
||||
pad_config* p_profile = x_device->config;
|
||||
if (p_profile == nullptr)
|
||||
return false;
|
||||
|
||||
pad->Init
|
||||
(
|
||||
|
@ -477,29 +481,29 @@ bool xinput_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::st
|
|||
CELL_PAD_DEV_TYPE_STANDARD
|
||||
);
|
||||
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.l2), CELL_PAD_CTRL_L2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.r2), CELL_PAD_CTRL_R2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->up), CELL_PAD_CTRL_UP);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->start), CELL_PAD_CTRL_START);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->l3), CELL_PAD_CTRL_L3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->r3), CELL_PAD_CTRL_R3);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->l1), CELL_PAD_CTRL_L1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->r1), CELL_PAD_CTRL_R1);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->l2), CELL_PAD_CTRL_L2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->r2), CELL_PAD_CTRL_R2);
|
||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, FindKeyCode(button_list, m_pad_config.ls_left), FindKeyCode(button_list, m_pad_config.ls_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, FindKeyCode(button_list, m_pad_config.ls_down), FindKeyCode(button_list, m_pad_config.ls_up));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, FindKeyCode(button_list, m_pad_config.rs_left), FindKeyCode(button_list, m_pad_config.rs_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, FindKeyCode(button_list, m_pad_config.rs_down), FindKeyCode(button_list, m_pad_config.rs_up));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, FindKeyCode(button_list, p_profile->ls_left), FindKeyCode(button_list, p_profile->ls_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, FindKeyCode(button_list, p_profile->ls_down), FindKeyCode(button_list, p_profile->ls_up));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, FindKeyCode(button_list, p_profile->rs_left), FindKeyCode(button_list, p_profile->rs_right));
|
||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, FindKeyCode(button_list, p_profile->rs_down), FindKeyCode(button_list, p_profile->rs_up));
|
||||
|
||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512);
|
||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399);
|
||||
|
@ -509,7 +513,7 @@ bool xinput_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::st
|
|||
pad->m_vibrateMotors.emplace_back(true, 0);
|
||||
pad->m_vibrateMotors.emplace_back(false, 0);
|
||||
|
||||
bindings.emplace_back(device_id, pad);
|
||||
bindings.emplace_back(x_device, pad);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/Config.h"
|
||||
#include "Emu/Io/PadHandler.h"
|
||||
#define NOMINMAX
|
||||
|
@ -95,6 +94,7 @@ class xinput_pad_handler final : public PadHandlerBase
|
|||
u8 largeVibrate{ 0 };
|
||||
u8 smallVibrate{ 0 };
|
||||
clock_t last_vibration{ 0 };
|
||||
pad_config* config{ nullptr };
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -109,6 +109,7 @@ public:
|
|||
void ThreadProc() override;
|
||||
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false, std::vector<std::string> buttons = {}) override;
|
||||
void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override;
|
||||
void init_config(pad_config* cfg, const std::string& name) override;
|
||||
|
||||
private:
|
||||
typedef void (WINAPI * PFN_XINPUTENABLE)(BOOL);
|
||||
|
@ -121,15 +122,16 @@ private:
|
|||
std::array<u16, XInputKeyCodes::KeyCodeCount> GetButtonValues(const XINPUT_STATE& state);
|
||||
void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override;
|
||||
|
||||
bool is_init;
|
||||
HMODULE library;
|
||||
PFN_XINPUTGETSTATE xinputGetState;
|
||||
PFN_XINPUTSETSTATE xinputSetState;
|
||||
PFN_XINPUTENABLE xinputEnable;
|
||||
PFN_XINPUTGETBATTERYINFORMATION xinputGetBatteryInformation;
|
||||
bool is_init{ false };
|
||||
HMODULE library{ nullptr };
|
||||
PFN_XINPUTGETSTATE xinputGetState{ nullptr };
|
||||
PFN_XINPUTSETSTATE xinputSetState{ nullptr };
|
||||
PFN_XINPUTENABLE xinputEnable{ nullptr };
|
||||
PFN_XINPUTGETBATTERYINFORMATION xinputGetBatteryInformation{ nullptr };
|
||||
|
||||
std::vector<u32> blacklist;
|
||||
std::vector<std::pair<std::shared_ptr<XInputDevice>, std::shared_ptr<Pad>>> bindings;
|
||||
std::shared_ptr<XInputDevice> m_dev;
|
||||
|
||||
// holds internal controller state change
|
||||
XINPUT_STATE state;
|
||||
|
|
Loading…
Add table
Reference in a new issue