Merge pull request #42 from Kovensky/xinput

Xinput input support
This commit is contained in:
Henrik Rydgård 2012-11-12 10:41:14 -08:00
commit de40220325
11 changed files with 242 additions and 43 deletions

View file

@ -66,48 +66,6 @@ void SampleControls() {
_ctrl_data &data = ctrl;
data.frame=1;//frame;
frame++;
#ifdef _WIN32
// TODO: Move this outta here!
data.buttons = 0;
int analogX = 128;
int analogY = 128;
if (GetAsyncKeyState(VK_SPACE))
data.buttons|=CTRL_START;
if (GetAsyncKeyState('V'))
data.buttons|=CTRL_SELECT;
if (GetAsyncKeyState('A'))
data.buttons|=CTRL_SQUARE;
if (GetAsyncKeyState('S'))
data.buttons|=CTRL_TRIANGLE;
if (GetAsyncKeyState('X'))
data.buttons|=CTRL_CIRCLE;
if (GetAsyncKeyState('Z'))
data.buttons|=CTRL_CROSS;
if (GetAsyncKeyState('Q'))
data.buttons|=CTRL_LTRIGGER;
if (GetAsyncKeyState('W'))
data.buttons|=CTRL_RTRIGGER;
if (GetAsyncKeyState(VK_UP)) {
data.buttons|=CTRL_UP;
analogY -= 100;
}
if (GetAsyncKeyState(VK_DOWN)) {
data.buttons|=CTRL_DOWN;
analogY += 100;
}
if (GetAsyncKeyState(VK_LEFT)) {
data.buttons|=CTRL_LEFT;
analogX -= 100;
}
if (GetAsyncKeyState(VK_RIGHT))
{
data.buttons|=CTRL_RIGHT;
analogX += 100;
}
data.analog[0] = analogX;
data.analog[1] = analogY;
#endif
}

13
Windows/InputDevice.cpp Normal file
View file

@ -0,0 +1,13 @@
#include "InputDevice.h"
#include "XinputDevice.h"
#include "KeyboardDevice.h"
#include <list>
#include <memory>
#define PUSH_BACK(Cls) do { list.push_back(std::shared_ptr<InputDevice>(new Cls())); } while (0)
std::list<std::shared_ptr<InputDevice>> getInputDevices() {
std::list<std::shared_ptr<InputDevice>> list;
PUSH_BACK(XinputDevice);
PUSH_BACK(KeyboardDevice);
return list;
}

13
Windows/InputDevice.h Normal file
View file

@ -0,0 +1,13 @@
#include "../Common/CommonTypes.h"
#include "../Core/HLE/sceCtrl.h"
#pragma once
class InputDevice
{
public:
virtual int UpdateState() = 0;
};
#include <list>
#include <memory>
std::list<std::shared_ptr<InputDevice>> getInputDevices();

View file

@ -0,0 +1,46 @@
#include "KeyboardDevice.h"
#include "../Common/CommonTypes.h"
#include "../Core/HLE/sceCtrl.h"
#include "WinUser.h"
static const unsigned short key_ctrl_map[] = {
VK_SPACE, CTRL_START,
'V', CTRL_SELECT,
'A', CTRL_SQUARE,
'S', CTRL_TRIANGLE,
'X', CTRL_CIRCLE,
'Z', CTRL_CROSS,
'Q', CTRL_LTRIGGER,
'W', CTRL_RTRIGGER,
VK_UP, CTRL_UP,
VK_DOWN, CTRL_DOWN,
VK_LEFT, CTRL_LEFT,
VK_RIGHT, CTRL_RIGHT,
};
int KeyboardDevice::UpdateState() {
float analogX = 0;
float analogY = 0;
for (int i = 0; i < sizeof(key_ctrl_map)/sizeof(key_ctrl_map[0]); i += 2) {
if (!GetAsyncKeyState(key_ctrl_map[i]))
__CtrlButtonUp(key_ctrl_map[i+1]);
else {
__CtrlButtonDown(key_ctrl_map[i+1]);
switch (key_ctrl_map[i]) {
case VK_UP:
analogY -= .8f;
break;
case VK_DOWN:
analogY += .8f;
break;
case VK_LEFT:
analogX -= .8f;
break;
case VK_RIGHT:
analogX += .8f;
break;
}
}
}
__CtrlSetAnalog(analogX, analogY);
return 0;
}

7
Windows/KeyboardDevice.h Normal file
View file

@ -0,0 +1,7 @@
#pragma once
#include "InputDevice.h"
class KeyboardDevice : public InputDevice {
public:
virtual int UpdateState();
};

View file

@ -141,7 +141,7 @@
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<AdditionalDependencies>Winmm.lib;Ws2_32.lib;opengl32.lib;glu32.lib;comctl32.lib;dsound.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Winmm.lib;Ws2_32.lib;opengl32.lib;glu32.lib;comctl32.lib;dsound.lib;xinput.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
@ -364,6 +364,8 @@
<ClCompile Include="Debugger\Debugger_MemoryDlg.cpp" />
<ClCompile Include="Debugger\Debugger_VFPUDlg.cpp" />
<ClCompile Include="EmuThread.cpp" />
<ClCompile Include="InputDevice.cpp" />
<ClCompile Include="KeyboardDevice.cpp" />
<ClCompile Include="W32Util\DialogManager.cpp" />
<ClCompile Include="W32Util\Misc.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">$(IntDir)%(Filename)2.obj</ObjectFileName>
@ -390,6 +392,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="XinputDevice.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\android\jni\EmuScreen.h" />
@ -403,6 +406,8 @@
<ClInclude Include="Debugger\Debugger_MemoryDlg.h" />
<ClInclude Include="Debugger\Debugger_VFPUDlg.h" />
<ClInclude Include="EmuThread.h" />
<ClInclude Include="InputDevice.h" />
<ClInclude Include="KeyboardDevice.h" />
<ClInclude Include="W32Util\DialogManager.h" />
<ClInclude Include="W32Util\Misc.h" />
<ClInclude Include="W32Util\PropertySheet.h" />
@ -417,6 +422,7 @@
<ClInclude Include="main.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="..\stdafx.h" />
<ClInclude Include="XinputDevice.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\android\atlasscript.txt" />

View file

@ -23,6 +23,9 @@
<Filter Include="Android">
<UniqueIdentifier>{d53d0871-8572-4393-822e-d14db0a88dab}</UniqueIdentifier>
</Filter>
<Filter Include="Windows\Input">
<UniqueIdentifier>{a1963305-bf88-43ef-8ba2-bb3933584b38}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Debugger\CtrlDisAsmView.cpp">
@ -92,6 +95,15 @@
<ClCompile Include="..\android\jni\UIShader.cpp">
<Filter>Android</Filter>
</ClCompile>
<ClCompile Include="XinputDevice.cpp">
<Filter>Windows\Input</Filter>
</ClCompile>
<ClCompile Include="KeyboardDevice.cpp">
<Filter>Windows\Input</Filter>
</ClCompile>
<ClCompile Include="InputDevice.cpp">
<Filter>Windows\Input</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Debugger\CtrlDisAsmView.h">
@ -161,6 +173,15 @@
<ClInclude Include="..\android\jni\UIShader.h">
<Filter>Android</Filter>
</ClInclude>
<ClInclude Include="InputDevice.h">
<Filter>Windows\Input</Filter>
</ClInclude>
<ClInclude Include="XinputDevice.h">
<Filter>Windows\Input</Filter>
</ClInclude>
<ClInclude Include="KeyboardDevice.h">
<Filter>Windows\Input</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="icon1.ico">

View file

@ -85,6 +85,9 @@ void WindowsHost::SetDebugMode(bool mode)
void WindowsHost::BeginFrame()
{
for (auto iter = this->input.begin(); iter != this->input.end(); iter++)
if ((*iter)->UpdateState() == 0)
break; // *iter is std::shared_ptr, **iter is InputDevice
GL_BeginFrame();
}
void WindowsHost::EndFrame()

View file

@ -1,4 +1,7 @@
#include "../Core/Host.h"
#include "InputDevice.h"
#include <list>
#include <memory>
class WindowsHost : public Host
{
@ -6,6 +9,7 @@ public:
WindowsHost(HWND _displayWindow)
{
displayWindow = _displayWindow;
input = getInputDevices();
}
void UpdateMemView();
void UpdateDisassembly();
@ -30,4 +34,5 @@ public:
private:
HWND displayWindow;
std::list<std::shared_ptr<InputDevice>> input;
};

110
Windows/XinputDevice.cpp Normal file
View file

@ -0,0 +1,110 @@
#include "stdafx.h"
#include "XinputDevice.h"
#include <limits.h>
#include <iostream>
XinputDevice::XinputDevice() {
ZeroMemory( &this->prevState, sizeof(this->prevState) );
this->check_delay = 0;
this->gamepad_idx = -1;
}
struct Stick {
float x;
float y;
};
static Stick NormalizedDeadzoneFilter(XINPUT_STATE &state);
int XinputDevice::UpdateState() {
if (this->check_delay-- > 0) return -1;
XINPUT_STATE state;
ZeroMemory( &state, sizeof(XINPUT_STATE) );
DWORD dwResult;
if (this->gamepad_idx >= 0)
dwResult = XInputGetState( this->gamepad_idx, &state );
else {
// use the first gamepad that responds
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
dwResult = XInputGetState( i, &state );
if (dwResult == ERROR_SUCCESS) {
this->gamepad_idx = i;
break;
}
}
}
if ( dwResult == ERROR_SUCCESS ) {
this->ApplyDiff(state);
Stick left = NormalizedDeadzoneFilter(state);
__CtrlSetAnalog(left.x, left.y);
this->prevState = state;
this->check_delay = 0;
return 0;
} else {
// wait check_delay frames before polling the controller again
this->gamepad_idx = -1;
this->check_delay = 100;
return -1;
}
}
// We only filter the left stick since PSP has no analog triggers or right stick
static Stick NormalizedDeadzoneFilter(XINPUT_STATE &state) {
static const short DEADZONE = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
Stick left;
left.x = state.Gamepad.sThumbLX;
left.y = state.Gamepad.sThumbLY;
float magnitude = sqrt(left.x*left.x + left.y*left.y);
Stick norm;
norm.x = left.x / magnitude;
norm.y = left.y / magnitude;
if (magnitude > DEADZONE) {
if (magnitude > 32767) magnitude = 32767;
// normalize the magnitude
magnitude -= DEADZONE;
magnitude /= (32767 - DEADZONE);
// normalize the axis
left.x = norm.x * magnitude;
left.y = norm.y * magnitude;
} else
left.x = left.y = 0;
return left;
}
static const unsigned short xinput_ctrl_map[] = {
XINPUT_GAMEPAD_DPAD_UP, CTRL_UP,
XINPUT_GAMEPAD_DPAD_DOWN, CTRL_DOWN,
XINPUT_GAMEPAD_DPAD_LEFT, CTRL_LEFT,
XINPUT_GAMEPAD_DPAD_RIGHT, CTRL_RIGHT,
XINPUT_GAMEPAD_START, CTRL_START,
XINPUT_GAMEPAD_BACK, CTRL_SELECT,
XINPUT_GAMEPAD_LEFT_SHOULDER, CTRL_LTRIGGER,
XINPUT_GAMEPAD_RIGHT_SHOULDER, CTRL_RTRIGGER,
XINPUT_GAMEPAD_A, CTRL_CROSS,
XINPUT_GAMEPAD_B, CTRL_CIRCLE,
XINPUT_GAMEPAD_X, CTRL_SQUARE,
XINPUT_GAMEPAD_Y, CTRL_TRIANGLE,
};
static inline u32 CtrlForXinput(int xinput) {
for (int i = 0; i < sizeof(xinput_ctrl_map)/sizeof(xinput_ctrl_map[0]); i += 2)
if (xinput_ctrl_map[i] == xinput) return (u32) xinput_ctrl_map[i+1];
return 0;
}
void XinputDevice::ApplyDiff(XINPUT_STATE &state) {
unsigned short pressed = state.Gamepad.wButtons & ~this->prevState.Gamepad.wButtons;
unsigned short released = ~state.Gamepad.wButtons & this->prevState.Gamepad.wButtons;
for (int i = 1; i < USHRT_MAX; i <<= 1) {
if (pressed & i)
__CtrlButtonDown(CtrlForXinput(i));
if (released & i)
__CtrlButtonUp(CtrlForXinput(i));
}
}

17
Windows/XinputDevice.h Normal file
View file

@ -0,0 +1,17 @@
#pragma once
#include "InputDevice.h"
#include "Xinput.h"
class XinputDevice :
public InputDevice
{
public:
XinputDevice();
virtual int UpdateState();
private:
void ApplyDiff(XINPUT_STATE &state);
int gamepad_idx;
int check_delay;
XINPUT_STATE prevState;
};