[TLAC]: add DIVALLER support
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
#include "DVLBinding.h"
|
||||
|
||||
namespace TLAC::Input
|
||||
{
|
||||
#define DivallerInstanceCheckDefault(checkFunc) (Divaller::InstanceInitialized() ? Divaller::GetInstance()->checkFunc : false)
|
||||
|
||||
DivallerBinding::DivallerBinding(DivallerButton button) : Button(button)
|
||||
{
|
||||
}
|
||||
|
||||
DivallerBinding::~DivallerBinding()
|
||||
{
|
||||
}
|
||||
|
||||
bool DivallerBinding::IsDown()
|
||||
{
|
||||
return DivallerInstanceCheckDefault(IsDown(Button));
|
||||
}
|
||||
|
||||
bool DivallerBinding::IsTapped()
|
||||
{
|
||||
return DivallerInstanceCheckDefault(IsTapped(Button));
|
||||
}
|
||||
|
||||
bool DivallerBinding::IsReleased()
|
||||
{
|
||||
return DivallerInstanceCheckDefault(IsReleased(Button));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "IInputBinding.h"
|
||||
#include "../Divaller/Divaller.h"
|
||||
|
||||
namespace TLAC::Input
|
||||
{
|
||||
class DivallerBinding : public IInputBinding
|
||||
{
|
||||
public:
|
||||
DivallerButton Button;
|
||||
|
||||
DivallerBinding(DivallerButton button);
|
||||
~DivallerBinding();
|
||||
|
||||
bool IsDown() override;
|
||||
bool IsTapped() override;
|
||||
bool IsReleased() override;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
#include "Divaller.h"
|
||||
#include "../../framework.h"
|
||||
#include "DivallerButton.h"
|
||||
#include "DivallerState.h"
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
namespace TLAC::Input
|
||||
{
|
||||
Divaller *Divaller::instance;
|
||||
|
||||
Divaller::Divaller()
|
||||
{
|
||||
memset(outputBuffer, 0, sizeof(outputBuffer));
|
||||
outputBuffer[0] = 0x44;
|
||||
outputBuffer[1] = 0x4c;
|
||||
outputBuffer[2] = 0x61;
|
||||
}
|
||||
|
||||
Divaller::~Divaller()
|
||||
{
|
||||
CloseHandle(hDeviceHandle);
|
||||
}
|
||||
|
||||
bool Divaller::TryInitializeInstance()
|
||||
{
|
||||
if (InstanceInitialized())
|
||||
return true;
|
||||
|
||||
Divaller *divaller = new Divaller();
|
||||
|
||||
BOOL success = divaller->Initialize();
|
||||
instance = success ? divaller : nullptr;
|
||||
|
||||
if (!success)
|
||||
delete divaller;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Divaller::Initialize()
|
||||
{
|
||||
HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if (hDevInfo == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("[TLAC] Divaller::Initialize(): SetupDiGetClassDevs returned INVALID_HANDLE_VALUE\n");
|
||||
return false;
|
||||
}
|
||||
LPCWSTR devPath = NULL;
|
||||
for (size_t i = 0;; i++)
|
||||
{
|
||||
SP_DEVICE_INTERFACE_DATA device_interface_data = {0};
|
||||
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
BOOL success = SetupDiEnumDeviceInterfaces(
|
||||
hDevInfo,
|
||||
NULL,
|
||||
&GUID_DEVINTERFACE_USB_DEVICE,
|
||||
(DWORD)i,
|
||||
&device_interface_data);
|
||||
if (!success)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ULONG required_length = 0;
|
||||
success = SetupDiGetDeviceInterfaceDetail(
|
||||
hDevInfo,
|
||||
&device_interface_data,
|
||||
NULL,
|
||||
0,
|
||||
&required_length,
|
||||
NULL);
|
||||
|
||||
UINT8 *interface_data = (UINT8 *)calloc(required_length, sizeof(UINT8));
|
||||
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)interface_data;
|
||||
device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
|
||||
ULONG actual_length = required_length;
|
||||
success = SetupDiGetDeviceInterfaceDetail(
|
||||
hDevInfo,
|
||||
&device_interface_data,
|
||||
device_interface_detail_data,
|
||||
actual_length,
|
||||
&required_length,
|
||||
NULL);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
wcsstr(device_interface_detail_data->DevicePath, L"vid_0e8f") == 0 ||
|
||||
wcsstr(device_interface_detail_data->DevicePath, L"pid_2213") == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
devPath = device_interface_detail_data->DevicePath;
|
||||
break;
|
||||
}
|
||||
if (devPath == NULL)
|
||||
{
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
return false;
|
||||
}
|
||||
hDeviceHandle = CreateFile(
|
||||
devPath,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
if (hDeviceHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("[TLAC] Divaller::Initialize(): Open device failed.\n");
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!WinUsb_Initialize(hDeviceHandle, &hInterfaceHandle))
|
||||
{
|
||||
printf("[TLAC] Divaller::Initialize(): WinUsb_Initialize failed.\n");
|
||||
std::cout << GetLastError() << std::endl;
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
CloseHandle(hDeviceHandle);
|
||||
return false;
|
||||
}
|
||||
|
||||
USB_INTERFACE_DESCRIPTOR USBInterfaceDescriptor;
|
||||
if (!WinUsb_QueryInterfaceSettings(hInterfaceHandle, 0, &USBInterfaceDescriptor))
|
||||
{
|
||||
std::cout << GetLastError() << std::endl;
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
CloseHandle(hDeviceHandle);
|
||||
return false;
|
||||
}
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Divaller::PollInput()
|
||||
{
|
||||
lastState = currentState;
|
||||
ULONG len = 0;
|
||||
memset(currentState.state, 0, sizeof(currentState.state));
|
||||
BOOL bResult = WinUsb_ReadPipe(hInterfaceHandle, (UCHAR)132, currentState.state, _countof(currentState.state), &len, nullptr);
|
||||
if (!bResult || currentState.state[0] != 0x42 || currentState.state[1] != 0x56 || currentState.state[2] != 0x5a)
|
||||
{
|
||||
printf("[TLAC] Divaller::PollInput(): WinUsb_ReadPipe failed.\n");
|
||||
std::cout << GetLastError() << std::endl;
|
||||
}
|
||||
SetLED();
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool Divaller::SetLED()
|
||||
{
|
||||
outputBuffer[3] &= 0x0F; // Reset Button LED
|
||||
outputBuffer[3] |= (!(*buttonLed >> 1 & 0x0001)) << 4; // SQUARE
|
||||
outputBuffer[3] |= (!(*buttonLed >> 3 & 0x0001)) << 5; // CIRCLE
|
||||
outputBuffer[3] |= (!(*buttonLed & 0x0001)) << 6; // TRIANGLE
|
||||
outputBuffer[3] |= (!(*buttonLed >> 2 & 0x0001)) << 7; // CROSS
|
||||
if (*sliderLedInit && !sliderLedData)
|
||||
{
|
||||
sliderLedData = reinterpret_cast<UCHAR *>(*(uint64_t *)(0x14cc5de40 + 0x68) + 0x189c);
|
||||
}
|
||||
if (sliderLedData)
|
||||
{
|
||||
for (int n = 0; n < 32; n++)
|
||||
{
|
||||
// LED number + 3 bytes header + color offset
|
||||
outputBuffer[(31 - n) * 3 + 3 + 3] = sliderLedData[n * 3 + 1]; // BLUE
|
||||
outputBuffer[(31 - n) * 3 + 3 + 2] = sliderLedData[n * 3 + 2]; // RED
|
||||
outputBuffer[(31 - n) * 3 + 3 + 1] = sliderLedData[n * 3 + 3]; // GREEN
|
||||
}
|
||||
}
|
||||
|
||||
ULONG len = 0;
|
||||
BOOL bResult = WinUsb_WritePipe(hInterfaceHandle, (UCHAR)0x03, outputBuffer, 100, &len, NULL);
|
||||
if (!bResult)
|
||||
{
|
||||
printf("[TLAC] Divaller::SetLED(): WinUsb_WritePipe failed.\n");
|
||||
std::cout << GetLastError() << std::endl;
|
||||
}
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool Divaller::IsDown(DivallerButton button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case DivallerButton::DVL_L1:
|
||||
return (currentState.state[5] >> 0) & 1;
|
||||
case DivallerButton::DVL_L2:
|
||||
return (currentState.state[4] >> 7) & 1;
|
||||
case DivallerButton::DVL_L3:
|
||||
return (currentState.state[4] >> 6) & 1;
|
||||
case DivallerButton::DVL_FN:
|
||||
return (currentState.state[3] >> 1) & 1;
|
||||
case DivallerButton::DVL_TRIANGLE:
|
||||
return (currentState.state[3] >> 4) & 1;
|
||||
case DivallerButton::DVL_SQUARE:
|
||||
return (currentState.state[3] >> 2) & 1;
|
||||
case DivallerButton::DVL_CROSS:
|
||||
return (currentState.state[3] >> 5) & 1;
|
||||
case DivallerButton::DVL_CIRCLE:
|
||||
return (currentState.state[3] >> 3) & 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Divaller::IsUp(DivallerButton button)
|
||||
{
|
||||
return !IsDown(button);
|
||||
}
|
||||
|
||||
bool Divaller::IsTapped(DivallerButton button)
|
||||
{
|
||||
return IsDown(button) && WasUp(button);
|
||||
}
|
||||
|
||||
bool Divaller::IsReleased(DivallerButton button)
|
||||
{
|
||||
return IsUp(button) && WasDown(button);
|
||||
}
|
||||
|
||||
bool Divaller::WasDown(DivallerButton button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case DivallerButton::DVL_L1:
|
||||
return (lastState.state[5] >> 0) & 1;
|
||||
case DivallerButton::DVL_L2:
|
||||
return (lastState.state[4] >> 7) & 1;
|
||||
case DivallerButton::DVL_L3:
|
||||
return (lastState.state[4] >> 6) & 1;
|
||||
case DivallerButton::DVL_FN:
|
||||
return (lastState.state[3] >> 1) & 1;
|
||||
case DivallerButton::DVL_TRIANGLE:
|
||||
return (lastState.state[3] >> 4) & 1;
|
||||
case DivallerButton::DVL_SQUARE:
|
||||
return (lastState.state[3] >> 2) & 1;
|
||||
case DivallerButton::DVL_CROSS:
|
||||
return (lastState.state[3] >> 5) & 1;
|
||||
case DivallerButton::DVL_CIRCLE:
|
||||
return (lastState.state[3] >> 3) & 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Divaller::WasUp(DivallerButton button)
|
||||
{
|
||||
return !WasDown(button);
|
||||
}
|
||||
|
||||
uint32_t Divaller::GetSlider()
|
||||
{
|
||||
uint32_t i = 0;
|
||||
i |= currentState.state[5] >> 4;
|
||||
i |= currentState.state[6] << 4;
|
||||
i |= currentState.state[7] << 12;
|
||||
i |= currentState.state[8] << 20;
|
||||
i |= currentState.state[9] << 28;
|
||||
// Reverse the bit order of uint32
|
||||
i = (i & 0xaaaaaaaa) >> 1 | (i & 0x55555555) << 1;
|
||||
i = (i & 0xcccccccc) >> 2 | (i & 0x33333333) << 2;
|
||||
i = (i & 0xf0f0f0f0) >> 4 | (i & 0x0f0f0f0f) << 4;
|
||||
i = (i & 0xff00ff00) >> 8 | (i & 0x00ff00ff) << 8;
|
||||
return i >> 16 | i << 16;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
#include "../IInputDevice.h"
|
||||
#include "DivallerState.h"
|
||||
#include "DivallerButton.h"
|
||||
#include <SetupAPI.h>
|
||||
#include <initguid.h>
|
||||
#include <usbiodef.h>
|
||||
#include <winusb.h>
|
||||
|
||||
namespace TLAC::Input
|
||||
{
|
||||
|
||||
class Divaller : public IInputDevice
|
||||
{
|
||||
public:
|
||||
Divaller();
|
||||
~Divaller();
|
||||
|
||||
static bool TryInitializeInstance();
|
||||
|
||||
bool Initialize();
|
||||
bool PollInput() override;
|
||||
bool SetLED();
|
||||
bool IsDown(DivallerButton button);
|
||||
bool IsUp(DivallerButton button);
|
||||
bool IsTapped(DivallerButton button);
|
||||
bool IsReleased(DivallerButton button);
|
||||
|
||||
bool WasDown(DivallerButton button);
|
||||
bool WasUp(DivallerButton button);
|
||||
uint32_t GetSlider();
|
||||
static inline bool InstanceInitialized() { return instance != nullptr; };
|
||||
static inline Divaller *GetInstance() { return instance; };
|
||||
static inline void DeleteInstance()
|
||||
{
|
||||
delete instance;
|
||||
instance = nullptr;
|
||||
};
|
||||
|
||||
private:
|
||||
static Divaller *instance;
|
||||
DivallerState lastState;
|
||||
DivallerState currentState;
|
||||
WINUSB_INTERFACE_HANDLE hInterfaceHandle;
|
||||
HANDLE hDeviceHandle;
|
||||
UCHAR outputBuffer[100];
|
||||
int *buttonLed = reinterpret_cast<int*>(0x14119b950);
|
||||
uint64_t *partionLed = reinterpret_cast<uint64_t*>(*(uint64_t*)0x140eda330 + 0xc9);
|
||||
uint64_t *sliderLedInit = reinterpret_cast<uint64_t*>((uint64_t*)0x14cc5dea8);
|
||||
UCHAR *sliderLedData = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
namespace TLAC::Input
|
||||
{
|
||||
enum DivallerButton : int
|
||||
{
|
||||
DVL_SQUARE = 0,
|
||||
DVL_CROSS = 1,
|
||||
DVL_CIRCLE = 2,
|
||||
DVL_TRIANGLE = 3,
|
||||
|
||||
DVL_FN = 4,
|
||||
|
||||
DVL_L1 = 5,
|
||||
DVL_L2 = 6,
|
||||
DVL_L3 = 7,
|
||||
|
||||
DVL_R1 = 8,
|
||||
DVL_R2 = 9,
|
||||
DVL_R3 = 10,
|
||||
|
||||
DVL_UP = 11,
|
||||
DVL_LEFT = 12,
|
||||
DVL_DOWN = 13,
|
||||
DVL_RIGHT = 14,
|
||||
|
||||
DVL_PAD = 11,
|
||||
DVL_SHARE = 12,
|
||||
DVL_HOME = 13,
|
||||
DVL_OPTION = 14
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "../../framework.h"
|
||||
namespace TLAC::Input
|
||||
{
|
||||
|
||||
struct DivallerState
|
||||
{
|
||||
uint8_t state[24];
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user