Created
August 8, 2016 14:03
-
-
Save Kaldaien/9685f1af8e0b37e4dea184941f006a0a to your computer and use it in GitHub Desktop.
Unx_Calibrate Source Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is part of UnX. | |
* | |
* UnX is free software : you can redistribute it | |
* and/or modify it under the terms of the GNU General Public License | |
* as published by The Free Software Foundation, either version 3 of | |
* the License, or (at your option) any later version. | |
* | |
* UnX is distributed in the hope that it will be useful, | |
* | |
* But WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with UnX. | |
* | |
* If not, see <http://www.gnu.org/licenses/>. | |
* | |
**/ | |
#include "stdafx.h" | |
#include "Resource.h" | |
#include <Windows.h> | |
#include <cstdint> | |
#include <Commctrl.h> | |
#include <comdef.h> | |
#include <dinput.h> | |
#pragma comment (lib, "dxguid.lib") | |
#include "parameter.h" | |
#include "input.h" | |
#include <mmsystem.h> | |
#pragma comment (lib, "winmm.lib") | |
struct unx_gamepad_s { | |
std::wstring tex_set = L"PlayStation_Glossy"; | |
bool legacy = false; | |
struct combo_s { | |
std::wstring unparsed = L""; | |
int buttons = 0; | |
int button0 = 0xffffffff; | |
int button1 = 0xffffffff; | |
int button2 = 0xffffffff; | |
bool lt = false; | |
bool rt = false; | |
} f1, f2, f3, f4, f5, screenshot; | |
struct remap_s { | |
struct buttons_s { | |
int X = JOY_BUTTON1; | |
int A = JOY_BUTTON2; | |
int B = JOY_BUTTON3; | |
int Y = JOY_BUTTON4; | |
int LB = JOY_BUTTON5; | |
int RB = JOY_BUTTON6; | |
int LT = JOY_BUTTON7; | |
int RT = JOY_BUTTON8; | |
int BACK = JOY_BUTTON9; | |
int START = JOY_BUTTON10; | |
int LS = JOY_BUTTON11; | |
int RS = JOY_BUTTON12; | |
} buttons; | |
// Post-Process the button map above so we do not | |
// have to constantly perform the operations | |
// below when polling a controller... | |
int map [12]; | |
static int indexToEnum (int idx) { | |
// For Axes | |
if (idx < 0) { | |
idx = (16 - idx); | |
} | |
return 1 << (idx - 1); | |
} | |
static int enumToIndex (unsigned int enum_val) { | |
int idx = 0; | |
// For Axes | |
bool axis = false; | |
if (enum_val >= (1 << 16)) | |
axis = true; | |
while (enum_val > 0) { | |
enum_val >>= 1; | |
idx++; | |
} | |
if (axis) { | |
idx -= 16; | |
idx = -idx; | |
} | |
return idx; | |
} | |
} remap; | |
} gamepad; | |
typedef struct _XINPUT_GAMEPAD { | |
WORD wButtons; | |
BYTE bLeftTrigger; | |
BYTE bRightTrigger; | |
SHORT sThumbLX; | |
SHORT sThumbLY; | |
SHORT sThumbRX; | |
SHORT sThumbRY; | |
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD; | |
typedef struct _XINPUT_STATE { | |
DWORD dwPacketNumber; | |
XINPUT_GAMEPAD Gamepad; | |
} XINPUT_STATE, *PXINPUT_STATE; | |
typedef DWORD (WINAPI *XInputGetState_pfn)( | |
_In_ DWORD dwUserIndex, | |
_Out_ XINPUT_STATE *pState | |
); | |
XInputGetState_pfn XInputGetState_Original = nullptr; | |
bool | |
IsControllerPluggedIn (UINT uJoyID) | |
{ | |
if (uJoyID == (UINT)-1) | |
return true; | |
XINPUT_STATE xstate; | |
static DWORD last_poll = timeGetTime (); | |
static DWORD dwRet = XInputGetState_Original (uJoyID, &xstate); | |
// This function is actually a performance hazzard when no controllers | |
// are plugged in, so ... throttle the sucker. | |
if (last_poll < timeGetTime () - 500UL) | |
dwRet = XInputGetState_Original (uJoyID, &xstate); | |
if (dwRet == ERROR_DEVICE_NOT_CONNECTED) | |
return false; | |
return true; | |
} | |
DWORD | |
WINAPI | |
XInputGetState_Detour ( _In_ DWORD dwUserIndex, | |
_Out_ XINPUT_STATE *pState ) | |
{ | |
int slot = 0; | |
DWORD dwRet = XInputGetState_Original (slot, pState); | |
if (dwRet == ERROR_NOT_CONNECTED) | |
dwRet = 0; | |
return dwRet; | |
} | |
/////////////////////////////////////////////////////////////////////////////// | |
// | |
// User32 Input APIs | |
// | |
/////////////////////////////////////////////////////////////////////////////// | |
uint32_t | |
UNXCAL_GetControllerButtonCount (void) | |
{ | |
JOYCAPSW caps; | |
if (JOYERR_NOERROR != joyGetDevCapsW (JOYSTICKID1, &caps, sizeof JOYCAPSW)) | |
return 32; | |
return caps.wNumButtons; | |
} | |
uint32_t | |
UNXCAL_GetControllerAxisCount (void) | |
{ | |
JOYCAPSW caps; | |
if (JOYERR_NOERROR != joyGetDevCapsW (JOYSTICKID1, &caps, sizeof JOYCAPSW)) | |
return 6; | |
return caps.wNumAxes; | |
} | |
wchar_t* | |
UNXCAL_GetControllerDescription (void) | |
{ | |
static wchar_t wszDescription [1024] = { L'\0' }; | |
JOYCAPSW caps; | |
joyGetDevCapsW (JOYSTICKID1, &caps, sizeof JOYCAPSW); | |
wsprintfW (wszDescription, L"Device: '%s' (%lu buttons, %lu axes)", caps.szPname, caps.wNumButtons, caps.wNumAxes); | |
return wszDescription; | |
} | |
BYTE | |
UNX_PollAxis (int axis, const JOYINFOEX& joy_ex, const JOYCAPSW& caps) | |
{ | |
switch (unx_gamepad_s::remap_s::enumToIndex (axis)) | |
{ | |
case -1: | |
return 255 * ((float)(joy_ex.dwXpos - caps.wXmin) / | |
(float)(caps.wXmax - caps.wXmin)); | |
case -2: | |
return 255 * ((float)(joy_ex.dwYpos - caps.wYmin) / | |
(float)(caps.wYmax - caps.wYmin)); | |
case -3: | |
return 255 * ((float)(joy_ex.dwZpos - caps.wZmin) / | |
(float)(caps.wZmax - caps.wZmin)); | |
case -4: | |
return 255 * ((float)(joy_ex.dwUpos - caps.wUmin) / | |
(float)(caps.wUmax - caps.wUmin)); | |
case -5: | |
return 255 * ((float)(joy_ex.dwVpos - caps.wVmin) / | |
(float)(caps.wVmax - caps.wVmin)); | |
case -6: | |
return 255 * ((float)(joy_ex.dwRpos - caps.wRmin) / | |
(float)(caps.wRmax - caps.wRmin)); | |
default: | |
return 255 * ((joy_ex.dwButtons & axis) ? 1 : 0); | |
} | |
} | |
void | |
UNXCAL_WaitForButtonRelease (void) | |
{ | |
JOYINFOEX joy_ex { 0 }; | |
joy_ex.dwSize = sizeof JOYINFOEX; | |
joy_ex.dwFlags = JOY_RETURNALL | JOY_RETURNPOVCTS | | |
JOY_RETURNCENTERED | JOY_USEDEADZONE | JOY_RETURNBUTTONS; | |
joyGetPosEx (JOYSTICKID1, &joy_ex); | |
while (true) { | |
static JOYCAPSW caps { 0 }; | |
if (caps.wMaxButtons == 0) | |
joyGetDevCapsW (JOYSTICKID1, &caps, sizeof JOYCAPSW); | |
bool axis_active = false; | |
const int num_axes = 6; | |
for (int i = 0; i < num_axes; i++) { | |
BYTE polled = UNX_PollAxis (1 << (16 + i), joy_ex, caps); | |
if (polled > 192) | |
axis_active = true; | |
} | |
joyGetPosEx (JOYSTICKID1, &joy_ex); | |
if (joy_ex.dwButtons == 0 && (! axis_active)) | |
return; | |
} | |
} | |
bool early_out = false; | |
bool try_axes = true; | |
int | |
UNXCAL_GetSingleButton (void) | |
{ | |
JOYINFOEX joy_ex { 0 }; | |
joy_ex.dwSize = sizeof JOYINFOEX; | |
joy_ex.dwFlags = JOY_RETURNALL | JOY_RETURNPOVCTS | | |
JOY_RETURNCENTERED | JOY_USEDEADZONE | JOY_RETURNBUTTONS; | |
joyGetPosEx (JOYSTICKID1, &joy_ex); | |
while (joy_ex.dwButtonNumber != 1 || (try_axes)) { | |
if (early_out) | |
return 0; | |
joy_ex.dwButtonNumber = 0; | |
joyGetPosEx (JOYSTICKID1, &joy_ex); | |
// Poll analog triggers | |
if (try_axes) { | |
static JOYCAPSW caps { 0 }; | |
if (caps.wMaxButtons == 0) | |
joyGetDevCapsW (JOYSTICKID1, &caps, sizeof JOYCAPSW); | |
const int num_axes = 6; | |
for (int i = 0; i < num_axes; i++) { | |
BYTE polled = UNX_PollAxis (1 << (16 + i), joy_ex, caps); | |
if (polled > 192) | |
return -(i + 1); | |
} | |
} | |
if (joy_ex.dwButtonNumber == 1) | |
break; | |
} | |
return gamepad.remap.enumToIndex (joy_ex.dwButtons); | |
} | |
#include <Windowsx.h> | |
HANDLE hButtonThread = 0; | |
CRITICAL_SECTION cs_poll { 0 }; | |
int polled_button = 0; | |
DWORD | |
WINAPI | |
GetButtonThread (LPVOID user) | |
{ | |
EnterCriticalSection (&cs_poll); | |
UNXCAL_WaitForButtonRelease (); | |
polled_button = | |
UNXCAL_GetSingleButton (); | |
LeaveCriticalSection (&cs_poll); | |
return 0; | |
} | |
enum task_item_t { | |
Content = TDE_CONTENT, | |
ExpandedInfo = TDE_EXPANDED_INFORMATION, | |
Footer = TDE_FOOTER, | |
MainInstruction = TDE_MAIN_INSTRUCTION | |
}; | |
void | |
UNX_TaskDialogUpdateText ( _In_ HWND hWnd, task_item_t item, std::wstring content ) | |
{ | |
SendMessage (hWnd, TDM_SET_ELEMENT_TEXT, TDE_CONTENT, (LPARAM)content.c_str ()); | |
} | |
HRESULT | |
CALLBACK | |
TaskDialogCallback ( | |
_In_ HWND hWnd, | |
_In_ UINT uNotification, | |
_In_ WPARAM wParam, | |
_In_ LPARAM lParam, | |
_In_ LONG_PTR dwRefData | |
) | |
{ | |
static int idx = 0; | |
static int idx_max = 11; | |
static wchar_t* descriptions [] = { L" PlayStation: <A HREF=\"\">Square</A> " | |
L" Xbox: <A HREF=\"\">X</A>", | |
L" PlayStation: <A HREF=\"\">Cross</A> " | |
L" Xbox: <A HREF=\"\">A</A>", | |
L" PlayStation: <A HREF=\"\">Circle</A> " | |
L" Xbox: <A HREF=\"\">B</A>", | |
L" PlayStation: <A HREF=\"\">Triangle</A> " | |
L" Xbox: <A HREF=\"\">Y</A>", | |
L" PlayStation: <A HREF=\"\">L1</A> " | |
L" Xbox: <A HREF=\"\">LB</A>", | |
L" PlayStation: <A HREF=\"\">R1</A> " | |
L" Xbox: <A HREF=\"\">RB</A>", | |
L" PlayStation: <A HREF=\"\">L2</A> " | |
L" Xbox: <A HREF=\"\">LT</A>", | |
L" PlayStation: <A HREF=\"\">R2</A> " | |
L" Xbox: <A HREF=\"\">RT</A>", | |
L" PlayStation: <A HREF=\"\">Select</A> " | |
L" Xbox: <A HREF=\"\">Back</A>", | |
L" PlayStation: <A HREF=\"\">Start</A> " | |
L" Xbox: <A HREF=\"\">Start</A>", | |
L" PlayStation: <A HREF=\"\">L3</A> " | |
L" Xbox: <A HREF=\"\">LS</A>", | |
L" PlayStation: <A HREF=\"\">R3</A> " | |
L" Xbox: <A HREF=\"\">RS</A>" }; | |
if (uNotification == TDN_DIALOG_CONSTRUCTED) | |
{ | |
idx = 0; | |
UNX_TaskDialogUpdateText ( hWnd, Content, descriptions [0] ); | |
polled_button = | |
idx; | |
SendMessage (hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0L, MAKEWPARAM (0, idx_max)); | |
SendMessage (hWnd, TDM_SET_PROGRESS_BAR_STATE, 0L, PBST_NORMAL); | |
SendMessage (hWnd, TDM_SET_PROGRESS_BAR_POS, idx, 0L); | |
static bool init = false; | |
if (! init) { | |
InitializeCriticalSectionAndSpinCount (&cs_poll, 10000UL); | |
init = true; | |
} | |
early_out = false; | |
hButtonThread = | |
CreateThread (nullptr, 0, GetButtonThread, nullptr, 0, nullptr); | |
} | |
if (uNotification == TDN_TIMER) | |
{ | |
if (TryEnterCriticalSection (&cs_poll)) { | |
SendMessage (hWnd, TDM_CLICK_BUTTON, IDOK, 0); | |
LeaveCriticalSection (&cs_poll); | |
} | |
} | |
if (uNotification == TDN_BUTTON_CLICKED) | |
{ | |
if (wParam == IDOK) { | |
early_out = true; | |
EnterCriticalSection (&cs_poll); | |
int* button = (int *)&gamepad.remap.buttons; | |
button [idx] = gamepad.remap.indexToEnum (polled_button); | |
LeaveCriticalSection (&cs_poll); | |
Sleep (100); | |
if (idx != idx_max) { | |
UNX_TaskDialogUpdateText (hWnd, Content, descriptions [++idx]); | |
polled_button = | |
idx; | |
SendMessage (hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0L, MAKEWPARAM (0, idx_max)); | |
SendMessage (hWnd, TDM_SET_PROGRESS_BAR_STATE, 0L, PBST_NORMAL); | |
SendMessage (hWnd, TDM_SET_PROGRESS_BAR_POS, idx, 0L); | |
early_out = false; | |
hButtonThread = | |
CreateThread (nullptr, 0, GetButtonThread, nullptr, 0, nullptr); | |
return S_FALSE; | |
} else { | |
return S_OK; | |
} | |
} | |
if (wParam == IDCANCEL) { | |
early_out = true; | |
EnterCriticalSection (&cs_poll); | |
early_out = false; | |
LeaveCriticalSection (&cs_poll); | |
Sleep (100); | |
UNX_TaskDialogUpdateText (hWnd, Content, descriptions [++idx]); | |
return S_OK; | |
} | |
} | |
return S_FALSE; | |
} | |
void | |
UnX::Calibrate::Init (void) | |
{ | |
unx::ParameterFactory factory; | |
unx::INI::File* pad_cfg = new unx::INI::File (L"UnX_Gamepad.ini"); | |
pad_cfg->parse (); | |
const size_t num_buttons = 16; | |
const size_t pad_lods = 2; | |
const wchar_t* | |
wszButtons [num_buttons] = | |
{ L"A", L"B", L"X", L"Y", | |
L"LB", L"RB", | |
L"LT", L"RT", | |
L"LS", L"RS", | |
L"UP", L"RIGHT", L"DOWN", L"LEFT", | |
L"START", L"SELECT" }; | |
unx::ParameterBool* supports_XInput = | |
(unx::ParameterBool *)factory.create_parameter <bool> (L"Disable XInput?"); | |
supports_XInput->register_to_ini (pad_cfg, L"Gamepad.Type", L"UsesXInput"); | |
//if (((unx::iParameter *)supports_XInput)->load ()) { | |
//gamepad.legacy = (! supports_XInput->get_value ()); | |
//} else { | |
//supports_XInput->store (true); | |
//} | |
//if (gamepad.legacy) | |
//{ | |
unx::ParameterInt* A = (unx::ParameterInt *)factory.create_parameter <int> (L"A"); | |
A->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_A"); | |
if (((unx::iParameter *)A)->load ()) { | |
gamepad.remap.buttons.A = (gamepad.remap.indexToEnum (A->get_value ())); | |
} else { | |
A->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.A)); | |
} | |
unx::ParameterInt* B = (unx::ParameterInt *)factory.create_parameter <int> (L"B"); | |
B->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_B"); | |
if (((unx::iParameter *)B)->load ()) { | |
gamepad.remap.buttons.B = (gamepad.remap.indexToEnum (B->get_value ())); | |
} else { | |
B->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.B)); | |
} | |
unx::ParameterInt* X = (unx::ParameterInt *)factory.create_parameter <int> (L"X"); | |
X->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_X"); | |
if (((unx::iParameter *)X)->load ()) { | |
gamepad.remap.buttons.X = (gamepad.remap.indexToEnum (X->get_value ())); | |
} else { | |
X->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.X)); | |
} | |
unx::ParameterInt* Y = (unx::ParameterInt *)factory.create_parameter <int> (L"Y"); | |
Y->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_Y"); | |
if (((unx::iParameter *)Y)->load ()) { | |
gamepad.remap.buttons.Y = (gamepad.remap.indexToEnum (Y->get_value ())); | |
} else { | |
Y->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.Y)); | |
} | |
unx::ParameterInt* START = (unx::ParameterInt *)factory.create_parameter <int> (L"START"); | |
START->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_Start"); | |
if (((unx::iParameter *)START)->load ()) { | |
gamepad.remap.buttons.START = (gamepad.remap.indexToEnum (START->get_value ())); | |
} else { | |
START->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.START)); | |
} | |
unx::ParameterInt* BACK = (unx::ParameterInt *)factory.create_parameter <int> (L"BACK"); | |
BACK->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_Back"); | |
if (((unx::iParameter *)BACK)->load ()) { | |
gamepad.remap.buttons.BACK = (gamepad.remap.indexToEnum (BACK->get_value ())); | |
} else { | |
BACK->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.BACK)); | |
} | |
unx::ParameterInt* LB = (unx::ParameterInt *)factory.create_parameter <int> (L"LB"); | |
LB->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_LB"); | |
if (((unx::iParameter *)LB)->load ()) { | |
gamepad.remap.buttons.LB = (gamepad.remap.indexToEnum (LB->get_value ())); | |
} else { | |
LB->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.LB)); | |
} | |
unx::ParameterInt* RB = (unx::ParameterInt *)factory.create_parameter <int> (L"RB"); | |
RB->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_RB"); | |
if (((unx::iParameter *)RB)->load ()) { | |
gamepad.remap.buttons.RB = (gamepad.remap.indexToEnum (RB->get_value ())); | |
} else { | |
RB->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.RB)); | |
} | |
unx::ParameterInt* LT = (unx::ParameterInt *)factory.create_parameter <int> (L"LT"); | |
LT->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_LT"); | |
if (((unx::iParameter *)LT)->load ()) { | |
gamepad.remap.buttons.LT = (gamepad.remap.indexToEnum (LT->get_value ())); | |
} else { | |
LT->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.LT)); | |
} | |
unx::ParameterInt* RT = (unx::ParameterInt *)factory.create_parameter <int> (L"RT"); | |
RT->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_RT"); | |
if (((unx::iParameter *)RT)->load ()) { | |
gamepad.remap.buttons.RT = (gamepad.remap.indexToEnum (RT->get_value ())); | |
} else { | |
RT->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.RT)); | |
} | |
unx::ParameterInt* LS = (unx::ParameterInt *)factory.create_parameter <int> (L"LS"); | |
LS->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_LS"); | |
if (((unx::iParameter *)LS)->load ()) { | |
gamepad.remap.buttons.LS = (gamepad.remap.indexToEnum (LS->get_value ())); | |
} else { | |
LS->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.LS)); | |
} | |
unx::ParameterInt* RS = (unx::ParameterInt *)factory.create_parameter <int> (L"RS"); | |
RS->register_to_ini (pad_cfg, L"Gamepad.Remap", L"XInput_RS"); | |
if (((unx::iParameter *)RS)->load ()) { | |
gamepad.remap.buttons.RS = (gamepad.remap.indexToEnum (RS->get_value ())); | |
} else { | |
RS->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.RS)); | |
} | |
//} | |
unx::ParameterStringW* combo_ESC = | |
(unx::ParameterStringW *) | |
factory.create_parameter <std::wstring> (L"ESC Buttons"); | |
unx::ParameterStringW* combo_F1 = | |
(unx::ParameterStringW *) | |
factory.create_parameter <std::wstring> (L"F1 Buttons"); | |
combo_F1->register_to_ini (pad_cfg, L"Gamepad.PC", L"F1"); | |
if (! combo_F1->load (gamepad.f1.unparsed)) { | |
combo_F1->store ( | |
(gamepad.f1.unparsed = L"Select+Cross") | |
); | |
} | |
unx::ParameterStringW* combo_F2 = | |
(unx::ParameterStringW *) | |
factory.create_parameter <std::wstring> (L"F2 Buttons"); | |
combo_F2->register_to_ini (pad_cfg, L"Gamepad.PC", L"F2"); | |
if (! combo_F2->load (gamepad.f2.unparsed)) { | |
combo_F2->store ( | |
(gamepad.f1.unparsed = L"Select+Circle") | |
); | |
} | |
unx::ParameterStringW* combo_F3 = | |
(unx::ParameterStringW *) | |
factory.create_parameter <std::wstring> (L"F3 Buttons"); | |
combo_F3->register_to_ini (pad_cfg, L"Gamepad.PC", L"F3"); | |
if (! combo_F3->load (gamepad.f3.unparsed)) { | |
combo_F3->store ( | |
(gamepad.f3.unparsed = L"Select+Square") | |
); | |
} | |
unx::ParameterStringW* combo_F4 = | |
(unx::ParameterStringW *) | |
factory.create_parameter <std::wstring> (L"F4 Buttons"); | |
combo_F4->register_to_ini (pad_cfg, L"Gamepad.PC", L"F4"); | |
if (! combo_F4->load (gamepad.f4.unparsed)) { | |
combo_F4->store ( | |
(gamepad.f4.unparsed = L"Select+L1") | |
); | |
} | |
unx::ParameterStringW* combo_F5 = | |
(unx::ParameterStringW *) | |
factory.create_parameter <std::wstring> (L"F5 Buttons"); | |
combo_F5->register_to_ini (pad_cfg, L"Gamepad.PC", L"F5"); | |
if (! combo_F5->load (gamepad.f5.unparsed)) { | |
combo_F5->store ( | |
(gamepad.f5.unparsed = L"Select+R1") | |
); | |
} | |
unx::ParameterStringW* combo_SS = | |
(unx::ParameterStringW *) | |
factory.create_parameter <std::wstring> (L"Screenshot Buttons"); | |
combo_SS->register_to_ini (pad_cfg, L"Gamepad.Steam", L"Screenshot"); | |
if (! combo_SS->load (gamepad.screenshot.unparsed)) { | |
combo_SS->store ( | |
(gamepad.screenshot.unparsed = L"Select+R3") | |
); | |
} | |
int nButtonPressed = 0; | |
TASKDIALOGCONFIG config = {0}; | |
int idx = 0; | |
config.cbSize = sizeof (config); | |
config.hInstance = GetModuleHandle (nullptr);//hInstance; | |
config.hwndParent = GetDesktopWindow (); | |
config.pszWindowTitle = L"\"Untitled\" Project X (Controller Calibration)"; | |
config.dwCommonButtons = TDCBF_CLOSE_BUTTON; | |
config.pButtons = nullptr; | |
config.cButtons = 0; | |
config.dwFlags = TDF_ENABLE_HYPERLINKS; | |
config.pfCallback = nullptr; | |
config.lpCallbackData = 0; | |
config.pszFooter = UNXCAL_GetControllerDescription (); | |
config.pszFooterIcon = TD_ERROR_ICON; | |
JOYCAPS joycaps; | |
if ((! joyGetNumDevs ()) || (JOYERR_NOERROR != joyGetDevCaps (JOYSTICKID1, &joycaps, sizeof joycaps)) || | |
( UNXCAL_GetControllerButtonCount () < 12 && | |
UNXCAL_GetControllerAxisCount () < 6 )) { | |
config.pszMainIcon = TD_WARNING_ICON; | |
if ( ( UNXCAL_GetControllerButtonCount () < 12 || | |
UNXCAL_GetControllerAxisCount () < 6 ) ) { | |
config.pszMainInstruction = L"Incompatible Controller Detected"; | |
config.pszContent = L"The game requires a controller with digital triggers or 6 analog axes for proper operation.\r\n\r\n" | |
L"\tPlease run your controller in XInput mode or set it up with digital triggers instead of analog."; | |
} else { | |
config.pszContent = L"Steam controllers are not DirectInput compatible.\r\n\r\n\tPlease review " | |
L"<A HREF=\"UnX_Gamepad.ini\">UnX_Gamepad.ini</A> for " | |
L"consistency."; | |
config.pszFooter = L"No DirectInput Compatible Controller Detected!"; | |
} | |
config.pszVerificationText = L"Check this box if you use an XInput controller."; | |
bool XInput; | |
if (supports_XInput->load (XInput) && XInput) | |
config.dwFlags |= TDF_VERIFICATION_FLAG_CHECKED; | |
BOOL verified; | |
TaskDialogIndirect (&config, nullptr, nullptr, &verified); | |
supports_XInput->store (verified); | |
pad_cfg->write (L"UnX_Gamepad.ini"); | |
delete pad_cfg; | |
return; | |
} | |
gamepad.legacy = true; | |
supports_XInput->store (false); | |
config.cbSize = sizeof (config); | |
config.hInstance = GetModuleHandle (nullptr);//hInstance; | |
config.hwndParent = GetDesktopWindow (); | |
config.pszWindowTitle = L"\"Untitled\" Project X (Controller Calibration)"; | |
config.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON; | |
config.pButtons = nullptr; | |
config.cButtons = 0; | |
config.dwFlags = TDF_CALLBACK_TIMER | TDF_ENABLE_HYPERLINKS | TDF_SHOW_PROGRESS_BAR/* | TDF_USE_HICON_MAIN*/; | |
config.pfCallback = TaskDialogCallback; | |
config.lpCallbackData = (LONG_PTR)&idx; | |
config.pszFooterIcon = TD_INFORMATION_ICON; | |
config.pszFooter = UNXCAL_GetControllerDescription (); | |
config.pszMainIcon = MAKEINTRESOURCE(IDI_UNX_CALIBRATE);// TD_INFORMATION_ICON; | |
config.pszMainInstruction = L"Please Press a Button on Your Controller"; | |
TaskDialogIndirect (&config, nullptr, nullptr, nullptr); | |
A->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.A)); | |
B->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.B)); | |
X->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.X)); | |
Y->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.Y)); | |
START->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.START)); | |
BACK->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.BACK)); | |
LB->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.LB)); | |
RB->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.RB)); | |
LT->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.LT)); | |
RT->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.RT)); | |
LS->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.LS)); | |
RS->store (gamepad.remap.enumToIndex (gamepad.remap.buttons.RS)); | |
pad_cfg->write (L"UnX_Gamepad.ini"); | |
delete pad_cfg; | |
// Post-Process our Remap Table | |
for (int i = 0; i < 12; i++) { | |
gamepad.remap.map [i] = | |
gamepad.remap.enumToIndex ( | |
((int *)&gamepad.remap.buttons) [ i ] | |
) - 1; | |
} | |
} | |
void | |
UnX::Calibrate::Shutdown (void) | |
{ | |
} | |
#define XINPUT_GAMEPAD_DPAD_UP 0x0001 | |
#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002 | |
#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004 | |
#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008 | |
#define XINPUT_GAMEPAD_START 0x0010 | |
#define XINPUT_GAMEPAD_BACK 0x0020 | |
#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040 | |
#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080 | |
#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 | |
#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 | |
#define XINPUT_GAMEPAD_LEFT_TRIGGER 0x10000 | |
#define XINPUT_GAMEPAD_RIGHT_TRIGGER 0x20000 | |
#define XINPUT_GAMEPAD_A 0x1000 | |
#define XINPUT_GAMEPAD_B 0x2000 | |
#define XINPUT_GAMEPAD_X 0x4000 | |
#define XINPUT_GAMEPAD_Y 0x8000 | |
struct button_map_state_s { | |
int buttons; | |
bool lt, rt; | |
}; | |
button_map_state_s | |
UNX_ParseButtonCombo (std::wstring combo, int* out) | |
{ | |
button_map_state_s state; | |
state.lt = false; | |
state.rt = false; | |
state.buttons = 0; | |
std::wstring map = combo; | |
if (! map.length ()) | |
return state; | |
wchar_t* wszMap = _wcsdup (map.c_str ()); | |
wchar_t* wszTok = wcstok (wszMap, L"+"); | |
while (wszTok != nullptr) { | |
int button = 0x00; | |
if ((! lstrcmpiW (wszTok, L"LB")) || (! lstrcmpiW (wszTok, L"L1"))) | |
button = XINPUT_GAMEPAD_LEFT_SHOULDER; | |
if ((! lstrcmpiW (wszTok, L"RB")) || (! lstrcmpiW (wszTok, L"R1"))) | |
button = XINPUT_GAMEPAD_RIGHT_SHOULDER; | |
if ((! lstrcmpiW (wszTok, L"LT")) || (! lstrcmpiW (wszTok, L"L2"))) | |
button = XINPUT_GAMEPAD_LEFT_TRIGGER; | |
if ((! lstrcmpiW (wszTok, L"RT")) || (! lstrcmpiW (wszTok, L"R2"))) | |
button = XINPUT_GAMEPAD_RIGHT_TRIGGER; | |
if ((! lstrcmpiW (wszTok, L"LS")) || (! lstrcmpiW (wszTok, L"L3"))) | |
button = XINPUT_GAMEPAD_LEFT_THUMB; | |
if ((! lstrcmpiW (wszTok, L"RS")) || (! lstrcmpiW (wszTok, L"R3"))) | |
button = XINPUT_GAMEPAD_RIGHT_THUMB; | |
if ((! lstrcmpiW (wszTok, L"Start"))) | |
button = XINPUT_GAMEPAD_START; | |
if ((! lstrcmpiW (wszTok, L"Back")) || (! lstrcmpiW (wszTok, L"Select"))) | |
button = XINPUT_GAMEPAD_BACK; | |
if ((! lstrcmpiW (wszTok, L"A")) || (! lstrcmpiW (wszTok, L"Cross"))) | |
button = XINPUT_GAMEPAD_A; | |
if ((! lstrcmpiW (wszTok, L"B")) || (! lstrcmpiW (wszTok, L"Circle"))) | |
button = XINPUT_GAMEPAD_B; | |
if ((! lstrcmpiW (wszTok, L"X")) || (! lstrcmpiW (wszTok, L"Square"))) | |
button = XINPUT_GAMEPAD_X; | |
if ((! lstrcmpiW (wszTok, L"Y")) || (! lstrcmpiW (wszTok, L"Triangle"))) | |
button = XINPUT_GAMEPAD_Y; | |
if (button == XINPUT_GAMEPAD_LEFT_TRIGGER) | |
state.lt = true; | |
else if (button == XINPUT_GAMEPAD_RIGHT_TRIGGER) | |
state.rt = true; | |
else if (button != 0x00) { | |
out [state.buttons++] = button; | |
} | |
//dll_log.Log (L"Button%lu: %s", state.buttons-1, wszTok); | |
wszTok = wcstok (nullptr, L"+"); | |
if (state.buttons > 1) | |
break; | |
} | |
free (wszMap); | |
return state; | |
} | |
#include <mmsystem.h> | |
void | |
UNX_SetupSpecialButtons (void) | |
{ | |
button_map_state_s state = | |
UNX_ParseButtonCombo ( gamepad.f1.unparsed, | |
&gamepad.f1.button0 ); | |
gamepad.f1.lt = state.lt; | |
gamepad.f1.rt = state.rt; | |
gamepad.f1.buttons = state.buttons; | |
state = | |
UNX_ParseButtonCombo ( gamepad.f2.unparsed, | |
&gamepad.f2.button0 ); | |
gamepad.f2.lt = state.lt; | |
gamepad.f2.rt = state.rt; | |
gamepad.f2.buttons = state.buttons; | |
state = | |
UNX_ParseButtonCombo ( gamepad.f3.unparsed, | |
&gamepad.f3.button0 ); | |
gamepad.f3.lt = state.lt; | |
gamepad.f3.rt = state.rt; | |
gamepad.f3.buttons = state.buttons; | |
state = | |
UNX_ParseButtonCombo ( gamepad.f4.unparsed, | |
&gamepad.f4.button0 ); | |
gamepad.f4.lt = state.lt; | |
gamepad.f4.rt = state.rt; | |
gamepad.f4.buttons = state.buttons; | |
state = | |
UNX_ParseButtonCombo ( gamepad.f5.unparsed, | |
&gamepad.f5.button0 ); | |
gamepad.f5.lt = state.lt; | |
gamepad.f5.rt = state.rt; | |
gamepad.f5.buttons = state.buttons; | |
state = | |
UNX_ParseButtonCombo ( gamepad.screenshot.unparsed, | |
&gamepad.screenshot.button0 ); | |
gamepad.screenshot.lt = state.lt; | |
gamepad.screenshot.rt = state.rt; | |
gamepad.screenshot.buttons = state.buttons; | |
} | |
#include "ini.h" | |
#include "parameter.h" | |
#include <queue> | |
struct combo_button_s { | |
combo_button_s ( | |
unx_gamepad_s::combo_s* combo_ | |
) : combo (combo_) { | |
state = false; | |
last_state = false; | |
}; | |
bool poll ( DWORD xi_ret, | |
XINPUT_GAMEPAD xi_gamepad ) | |
{ | |
last_state = state; | |
state = | |
(xi_ret == 0 && | |
combo->buttons != 0 && | |
((! combo->lt) || xi_gamepad.bLeftTrigger) && | |
((! combo->rt) || xi_gamepad.bRightTrigger) && | |
xi_gamepad.wButtons & (WORD)combo->button0 && | |
xi_gamepad.wButtons & (WORD)combo->button1 && | |
xi_gamepad.wButtons & (WORD)combo->button2); | |
return state; | |
} | |
bool wasJustPressed (void) { | |
return state && (! last_state); | |
} | |
unx_gamepad_s::combo_s* | |
combo; | |
bool state; | |
bool last_state; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment