mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-12-21 01:37:04 +00:00
Add all the files
This commit is contained in:
parent
e3db07a16a
commit
d60742f52b
1445 changed files with 430238 additions and 0 deletions
151
src/input/api/XInput/XInputController.cpp
Normal file
151
src/input/api/XInput/XInputController.cpp
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#include "input/api/XInput/XInputController.h"
|
||||
|
||||
XInputController::XInputController(uint32 index)
|
||||
: base_type(fmt::format("{}", index), fmt::format("Controller {}", index + 1))
|
||||
{
|
||||
if (index >= XUSER_MAX_COUNT)
|
||||
throw std::runtime_error(fmt::format("invalid xinput index {} (must be smaller than {})", index,
|
||||
XUSER_MAX_COUNT));
|
||||
|
||||
m_index = index;
|
||||
|
||||
m_settings.axis.deadzone = m_settings.rotation.deadzone = m_settings.trigger.deadzone = 0.15f;
|
||||
}
|
||||
|
||||
bool XInputController::connect()
|
||||
{
|
||||
if (m_connected)
|
||||
return true;
|
||||
|
||||
m_has_battery = false;
|
||||
|
||||
XINPUT_CAPABILITIES caps{};
|
||||
m_connected = m_provider->m_XInputGetCapabilities(m_index, XINPUT_FLAG_GAMEPAD, &caps) !=
|
||||
ERROR_DEVICE_NOT_CONNECTED;
|
||||
if (!m_connected) return false;
|
||||
|
||||
m_has_rumble = (caps.Vibration.wLeftMotorSpeed > 0) || (caps.Vibration.wRightMotorSpeed > 0);
|
||||
|
||||
if (m_provider->m_XInputGetBatteryInformation)
|
||||
{
|
||||
XINPUT_BATTERY_INFORMATION battery{};
|
||||
if (m_provider->m_XInputGetBatteryInformation(m_index, BATTERY_DEVTYPE_GAMEPAD, &battery) == ERROR_SUCCESS)
|
||||
{
|
||||
m_has_battery = (battery.BatteryType == BATTERY_TYPE_ALKALINE || battery.BatteryType ==
|
||||
BATTERY_TYPE_NIMH);
|
||||
}
|
||||
}
|
||||
|
||||
return m_connected;
|
||||
}
|
||||
|
||||
bool XInputController::is_connected()
|
||||
{
|
||||
return m_connected;
|
||||
}
|
||||
|
||||
|
||||
void XInputController::start_rumble()
|
||||
{
|
||||
if (!has_rumble() || m_settings.rumble <= 0)
|
||||
return;
|
||||
|
||||
XINPUT_VIBRATION vibration;
|
||||
vibration.wLeftMotorSpeed = static_cast<WORD>(m_settings.rumble * std::numeric_limits<uint16>::max());
|
||||
vibration.wRightMotorSpeed = static_cast<WORD>(m_settings.rumble * std::numeric_limits<uint16>::max());
|
||||
m_provider->m_XInputSetState(m_index, &vibration);
|
||||
}
|
||||
|
||||
void XInputController::stop_rumble()
|
||||
{
|
||||
if (!has_rumble())
|
||||
return;
|
||||
|
||||
XINPUT_VIBRATION vibration{};
|
||||
m_provider->m_XInputSetState(m_index, &vibration);
|
||||
}
|
||||
|
||||
bool XInputController::has_low_battery()
|
||||
{
|
||||
if (!has_battery())
|
||||
return false;
|
||||
|
||||
XINPUT_BATTERY_INFORMATION battery{};
|
||||
if (m_provider->m_XInputGetBatteryInformation(m_index, BATTERY_DEVTYPE_GAMEPAD, &battery) == ERROR_SUCCESS)
|
||||
{
|
||||
return (battery.BatteryType == BATTERY_TYPE_ALKALINE || battery.BatteryType == BATTERY_TYPE_NIMH) && battery
|
||||
.BatteryLevel <= BATTERY_LEVEL_LOW;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string XInputController::get_button_name(uint64 button) const
|
||||
{
|
||||
switch (1ULL << button)
|
||||
{
|
||||
case XINPUT_GAMEPAD_A: return "A";
|
||||
case XINPUT_GAMEPAD_B: return "B";
|
||||
case XINPUT_GAMEPAD_X: return "X";
|
||||
case XINPUT_GAMEPAD_Y: return "Y";
|
||||
|
||||
case XINPUT_GAMEPAD_LEFT_SHOULDER: return "L";
|
||||
case XINPUT_GAMEPAD_RIGHT_SHOULDER: return "R";
|
||||
|
||||
case XINPUT_GAMEPAD_START: return "Start";
|
||||
case XINPUT_GAMEPAD_BACK: return "Select";
|
||||
|
||||
case XINPUT_GAMEPAD_LEFT_THUMB: return "L-Stick";
|
||||
case XINPUT_GAMEPAD_RIGHT_THUMB: return "R-Stick";
|
||||
case XINPUT_GAMEPAD_DPAD_UP: return "DPAD-Up";
|
||||
case XINPUT_GAMEPAD_DPAD_DOWN: return "DPAD-Down";
|
||||
case XINPUT_GAMEPAD_DPAD_LEFT: return "DPAD-Left";
|
||||
case XINPUT_GAMEPAD_DPAD_RIGHT: return "DPAD-Right";
|
||||
}
|
||||
|
||||
return Controller::get_button_name(button);
|
||||
}
|
||||
|
||||
ControllerState XInputController::raw_state()
|
||||
{
|
||||
ControllerState result{};
|
||||
if (!m_connected)
|
||||
return result;
|
||||
|
||||
XINPUT_STATE state;
|
||||
if (m_provider->m_XInputGetState(m_index, &state) != ERROR_SUCCESS)
|
||||
{
|
||||
m_connected = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Buttons
|
||||
result.buttons = state.Gamepad.wButtons;
|
||||
|
||||
if (state.Gamepad.sThumbLX > 0)
|
||||
result.axis.x = (float)state.Gamepad.sThumbLX / std::numeric_limits<sint16>::max();
|
||||
else if (state.Gamepad.sThumbLX < 0)
|
||||
result.axis.x = (float)-state.Gamepad.sThumbLX / std::numeric_limits<sint16>::min();
|
||||
|
||||
if (state.Gamepad.sThumbLY > 0)
|
||||
result.axis.y = (float)state.Gamepad.sThumbLY / std::numeric_limits<sint16>::max();
|
||||
else if (state.Gamepad.sThumbLY < 0)
|
||||
result.axis.y = (float)-state.Gamepad.sThumbLY / std::numeric_limits<sint16>::min();
|
||||
|
||||
// Right Stick
|
||||
if (state.Gamepad.sThumbRX > 0)
|
||||
result.rotation.x = (float)state.Gamepad.sThumbRX / std::numeric_limits<sint16>::max();
|
||||
else if (state.Gamepad.sThumbRX < 0)
|
||||
result.rotation.x = (float)-state.Gamepad.sThumbRX / std::numeric_limits<sint16>::min();
|
||||
|
||||
if (state.Gamepad.sThumbRY > 0)
|
||||
result.rotation.y = (float)state.Gamepad.sThumbRY / std::numeric_limits<sint16>::max();
|
||||
else if (state.Gamepad.sThumbRY < 0)
|
||||
result.rotation.y = (float)-state.Gamepad.sThumbRY / std::numeric_limits<sint16>::min();
|
||||
|
||||
// Trigger
|
||||
result.trigger.x = (float)state.Gamepad.bLeftTrigger / std::numeric_limits<uint8>::max();
|
||||
result.trigger.y = (float)state.Gamepad.bRightTrigger / std::numeric_limits<uint8>::max();
|
||||
|
||||
return result;
|
||||
}
|
||||
38
src/input/api/XInput/XInputController.h
Normal file
38
src/input/api/XInput/XInputController.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include "input/api/XInput/XInputControllerProvider.h"
|
||||
#include "input/api/Controller.h"
|
||||
|
||||
class XInputController : public Controller<XInputControllerProvider>
|
||||
{
|
||||
public:
|
||||
XInputController(uint32 index);
|
||||
|
||||
std::string_view api_name() const override
|
||||
{
|
||||
static_assert(to_string(InputAPI::XInput) == "XInput");
|
||||
return to_string(InputAPI::XInput);
|
||||
}
|
||||
InputAPI::Type api() const override { return InputAPI::XInput; }
|
||||
|
||||
bool connect() override;
|
||||
bool is_connected() override;
|
||||
|
||||
bool has_rumble() override { return m_has_rumble; }
|
||||
bool has_battery() override { return m_has_battery; }
|
||||
bool has_low_battery() override;
|
||||
|
||||
void start_rumble() override;
|
||||
void stop_rumble() override;
|
||||
|
||||
std::string get_button_name(uint64 button) const override;
|
||||
|
||||
protected:
|
||||
ControllerState raw_state() override;
|
||||
|
||||
private:
|
||||
uint32 m_index;
|
||||
bool m_connected = false;
|
||||
bool m_has_battery = false;
|
||||
bool m_has_rumble = false;
|
||||
};
|
||||
57
src/input/api/XInput/XInputControllerProvider.cpp
Normal file
57
src/input/api/XInput/XInputControllerProvider.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include <Windows.h>
|
||||
|
||||
#include "input/api/XInput/XInputControllerProvider.h"
|
||||
#include "input/api/XInput/XInputController.h"
|
||||
|
||||
XInputControllerProvider::XInputControllerProvider()
|
||||
{
|
||||
// try to load newest to oldest
|
||||
m_module = LoadLibraryA("XInput1_4.DLL");
|
||||
if (!m_module)
|
||||
{
|
||||
m_module = LoadLibraryA("XInput1_3.DLL");
|
||||
if (!m_module)
|
||||
{
|
||||
m_module = LoadLibraryA("XInput9_1_0.dll");
|
||||
if (!m_module)
|
||||
throw std::runtime_error("can't load any xinput dll");
|
||||
}
|
||||
}
|
||||
|
||||
#define GET_XINPUT_PROC(__FUNC__) m_##__FUNC__ = (decltype(m_##__FUNC__))GetProcAddress(m_module, #__FUNC__)
|
||||
GET_XINPUT_PROC(XInputGetCapabilities);
|
||||
GET_XINPUT_PROC(XInputGetState);
|
||||
GET_XINPUT_PROC(XInputSetState);
|
||||
|
||||
if (!m_XInputGetCapabilities || !m_XInputGetState || !m_XInputSetState)
|
||||
{
|
||||
FreeLibrary(m_module);
|
||||
throw std::runtime_error("can't find necessary xinput functions");
|
||||
}
|
||||
|
||||
// only available in XInput1_4 and XInput1_3
|
||||
GET_XINPUT_PROC(XInputGetBatteryInformation);
|
||||
#undef GET_XINPUT_PROC
|
||||
|
||||
}
|
||||
|
||||
XInputControllerProvider::~XInputControllerProvider()
|
||||
{
|
||||
if (m_module)
|
||||
FreeLibrary(m_module);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<ControllerBase>> XInputControllerProvider::get_controllers()
|
||||
{
|
||||
std::vector<std::shared_ptr<ControllerBase>> result;
|
||||
for(DWORD i = 0; i < XUSER_MAX_COUNT; ++i)
|
||||
{
|
||||
XINPUT_CAPABILITIES caps;
|
||||
if (m_XInputGetCapabilities(i, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS)
|
||||
{
|
||||
result.emplace_back(std::make_shared<XInputController>(i));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
32
src/input/api/XInput/XInputControllerProvider.h
Normal file
32
src/input/api/XInput/XInputControllerProvider.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#if BOOST_OS_WINDOWS
|
||||
#include "input/api/ControllerProvider.h"
|
||||
|
||||
#include <Xinput.h>
|
||||
|
||||
#ifndef HAS_XINPUT
|
||||
#define HAS_XINPUT 1
|
||||
#endif
|
||||
|
||||
|
||||
class XInputControllerProvider : public ControllerProviderBase
|
||||
{
|
||||
friend class XInputController;
|
||||
public:
|
||||
XInputControllerProvider();
|
||||
~XInputControllerProvider() override;
|
||||
|
||||
inline static InputAPI::Type kAPIType = InputAPI::XInput;
|
||||
InputAPI::Type api() const override { return kAPIType; }
|
||||
|
||||
std::vector<std::shared_ptr<ControllerBase>> get_controllers() override;
|
||||
|
||||
private:
|
||||
HMODULE m_module = nullptr;
|
||||
decltype(&XInputGetBatteryInformation) m_XInputGetBatteryInformation;
|
||||
decltype(&XInputGetCapabilities) m_XInputGetCapabilities;
|
||||
decltype(&XInputSetState) m_XInputSetState;
|
||||
decltype(&XInputGetState) m_XInputGetState;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue