mirror of https://github.com/PCSX2/pcsx2.git
reformat lilypad
Note: I'm worried on the EXPORT/CALLBACK behavior on multiple OS
This commit is contained in:
parent
f06f44c30a
commit
d6ae5bfafa
File diff suppressed because it is too large
Load Diff
|
@ -27,15 +27,17 @@ enum PadType {
|
|||
PopnPad
|
||||
};
|
||||
|
||||
const int numPadTypes= 4;
|
||||
const int numPadTypes = 4;
|
||||
extern const wchar_t *padTypes[numPadTypes];
|
||||
|
||||
struct PadConfig {
|
||||
struct PadConfig
|
||||
{
|
||||
PadType type;
|
||||
u8 autoAnalog;
|
||||
};
|
||||
|
||||
struct GeneralConfig {
|
||||
struct GeneralConfig
|
||||
{
|
||||
public:
|
||||
PadConfig padConfigs[2][4];
|
||||
|
||||
|
@ -47,14 +49,17 @@ public:
|
|||
// Derived value, calculated by GetInput().
|
||||
u8 ignoreKeys;
|
||||
|
||||
union {
|
||||
struct {
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 forceHide;
|
||||
u8 mouseUnfocus;
|
||||
u8 background;
|
||||
u8 multipleBinding;
|
||||
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
u8 directInput;
|
||||
u8 xInput;
|
||||
u8 dualShock3;
|
||||
|
@ -73,8 +78,8 @@ public:
|
|||
u8 bools[15];
|
||||
};
|
||||
|
||||
wchar_t lastSaveConfigPath[MAX_PATH+1];
|
||||
wchar_t lastSaveConfigFileName[MAX_PATH+1];
|
||||
wchar_t lastSaveConfigPath[MAX_PATH + 1];
|
||||
wchar_t lastSaveConfigFileName[MAX_PATH + 1];
|
||||
};
|
||||
|
||||
extern GeneralConfig config;
|
||||
|
|
|
@ -33,7 +33,8 @@
|
|||
#include "Linux/JoyEvdev.h"
|
||||
#endif
|
||||
|
||||
void EnumDevices(int hideDXXinput) {
|
||||
void EnumDevices(int hideDXXinput)
|
||||
{
|
||||
// Needed for enumeration of some device types.
|
||||
dm->ReleaseInput();
|
||||
InputDeviceManager *oldDm = dm;
|
||||
|
|
|
@ -16,4 +16,3 @@
|
|||
*/
|
||||
|
||||
void EnumDevices(int hideDXXinput);
|
||||
|
||||
|
|
|
@ -25,14 +25,14 @@
|
|||
|
||||
Device *dev;
|
||||
|
||||
INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int i;
|
||||
HWND hWndList = GetDlgItem(hWnd, IDC_LIST);
|
||||
static int fullRefresh;
|
||||
if (dev) {
|
||||
switch (uMsg) {
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
case WM_INITDIALOG: {
|
||||
fullRefresh = 1;
|
||||
SetWindowText(hWnd, dev->displayName);
|
||||
LVCOLUMNW c;
|
||||
|
@ -47,16 +47,15 @@ INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM
|
|||
LVITEM item;
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iSubItem = 0;
|
||||
for (i=0; i<dev->numVirtualControls; i++) {
|
||||
item.pszText = dev->GetVirtualControlName(dev->virtualControls+i);
|
||||
for (i = 0; i < dev->numVirtualControls; i++) {
|
||||
item.pszText = dev->GetVirtualControlName(dev->virtualControls + i);
|
||||
item.iItem = i;
|
||||
ListView_InsertItem(hWndList, &item);
|
||||
}
|
||||
SetTimer(hWnd, 1, 200, 0);
|
||||
}
|
||||
//break;
|
||||
case WM_TIMER:
|
||||
{
|
||||
case WM_TIMER: {
|
||||
hWndButtonProc.SetWndHandle(hWndList);
|
||||
InitInfo info = {0, 1, hWnd, &hWndButtonProc};
|
||||
dm->Update(&info);
|
||||
|
@ -67,14 +66,13 @@ INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM
|
|||
//LockWindowUpdate(hWndList);
|
||||
if (!dev->active) {
|
||||
item.pszText = L"?";
|
||||
for (i=0; i<dev->numVirtualControls; i++) {
|
||||
for (i = 0; i < dev->numVirtualControls; i++) {
|
||||
item.iItem = i;
|
||||
ListView_SetItem(hWndList, &item);
|
||||
}
|
||||
fullRefresh = 1;
|
||||
}
|
||||
else {
|
||||
for (i=0; i<dev->numVirtualControls; i++) {
|
||||
} else {
|
||||
for (i = 0; i < dev->numVirtualControls; i++) {
|
||||
if (fullRefresh || dev->virtualControlState[i] != dev->oldVirtualControlState[i]) {
|
||||
|
||||
VirtualControl *c = dev->virtualControls + i;
|
||||
|
@ -82,18 +80,17 @@ INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM
|
|||
int val = dev->virtualControlState[i];
|
||||
if (c->uid & (UID_POV)) {
|
||||
wsprintfW(temp, L"%i", val);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
wchar_t *sign = L"";
|
||||
if (val < 0) {
|
||||
sign = L"-";
|
||||
val = -val;
|
||||
}
|
||||
if ((c->uid& UID_AXIS) && val) {
|
||||
if ((c->uid & UID_AXIS) && val) {
|
||||
val = val;
|
||||
}
|
||||
val = (int)floor(0.5 + val * 1000.0 / (double)FULLY_DOWN);
|
||||
wsprintfW(temp, L"%s%i.%03i", sign, val/1000, val%1000);
|
||||
wsprintfW(temp, L"%s%i.%03i", sign, val / 1000, val % 1000);
|
||||
}
|
||||
item.pszText = temp;
|
||||
item.iItem = i;
|
||||
|
@ -106,17 +103,17 @@ INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM
|
|||
//LockWindowUpdate(0);
|
||||
//ShowWindow(hWndList, 1);
|
||||
//UpdateWindow(hWnd);
|
||||
}
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
NMLVKEYDOWN *n = (NMLVKEYDOWN *) lParam;
|
||||
} break;
|
||||
case WM_NOTIFY: {
|
||||
NMLVKEYDOWN *n = (NMLVKEYDOWN *)lParam;
|
||||
// Don't always get the notification when testing DirectInput non-keyboard devices.
|
||||
// Don't get it (Or want it) when testing keyboards.
|
||||
if (n->hdr.idFrom != IDC_LIST || n->hdr.code != LVN_KEYDOWN || n->wVKey != VK_ESCAPE) break;
|
||||
if (n->hdr.idFrom != IDC_LIST || n->hdr.code != LVN_KEYDOWN || n->wVKey != VK_ESCAPE)
|
||||
break;
|
||||
}
|
||||
case WM_ACTIVATE:
|
||||
if (uMsg == WM_ACTIVATE && wParam != WA_INACTIVE) break;
|
||||
if (uMsg == WM_ACTIVATE && wParam != WA_INACTIVE)
|
||||
break;
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
KillTimer(hWnd, 1);
|
||||
|
@ -132,13 +129,16 @@ INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Diagnose(int id, HWND hWnd) {
|
||||
void Diagnose(int id, HWND hWnd)
|
||||
{
|
||||
// init = 0;
|
||||
dev = dm->devices[id];
|
||||
for (int i=0; i<dm->numDevices; i++) {
|
||||
if (i != id) dm->DisableDevice(i);
|
||||
for (int i = 0; i < dm->numDevices; i++) {
|
||||
if (i != id)
|
||||
dm->DisableDevice(i);
|
||||
// Shouldn't be needed.
|
||||
else dm->EnableDevice(i);
|
||||
else
|
||||
dm->EnableDevice(i);
|
||||
}
|
||||
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIAG), hWnd, DiagDialog);
|
||||
ClearKeyQueue();
|
||||
|
|
|
@ -32,43 +32,56 @@
|
|||
// media SDK also be installed for a simple macro. This is
|
||||
// simpler and less silly.
|
||||
#ifndef SAFE_RELEASE
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
#define SAFE_RELEASE(p) \
|
||||
{ \
|
||||
if (p) { \
|
||||
(p)->Release(); \
|
||||
(p) = NULL; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
// Aka htons, without the winsock dependency.
|
||||
inline static u16 flipShort(u16 s) {
|
||||
return (s>>8) | (s<<8);
|
||||
inline static u16 flipShort(u16 s)
|
||||
{
|
||||
return (s >> 8) | (s << 8);
|
||||
}
|
||||
|
||||
// Aka htonl, without the winsock dependency.
|
||||
inline static u32 flipLong(u32 l) {
|
||||
return (((u32)flipShort((u16)l))<<16) | flipShort((u16)(l>>16));
|
||||
inline static u32 flipLong(u32 l)
|
||||
{
|
||||
return (((u32)flipShort((u16)l)) << 16) | flipShort((u16)(l >> 16));
|
||||
}
|
||||
|
||||
static void GUIDtoString(wchar_t *data, const GUID *pg) {
|
||||
static void GUIDtoString(wchar_t *data, const GUID *pg)
|
||||
{
|
||||
wsprintfW(data, L"%08X-%04X-%04X-%04X-%04X%08X",
|
||||
pg->Data1, (u32)pg->Data2, (u32)pg->Data3,
|
||||
flipShort(((u16*)pg->Data4)[0]),
|
||||
flipShort(((u16*)pg->Data4)[1]),
|
||||
flipLong(((u32*)pg->Data4)[1]));
|
||||
flipShort(((u16 *)pg->Data4)[0]),
|
||||
flipShort(((u16 *)pg->Data4)[1]),
|
||||
flipLong(((u32 *)pg->Data4)[1]));
|
||||
}
|
||||
|
||||
struct DirectInput8Data {
|
||||
IDirectInput8* lpDI8;
|
||||
struct DirectInput8Data
|
||||
{
|
||||
IDirectInput8 *lpDI8;
|
||||
int refCount;
|
||||
int deviceCount;
|
||||
};
|
||||
|
||||
DirectInput8Data di8d = {0,0,0};
|
||||
DirectInput8Data di8d = {0, 0, 0};
|
||||
|
||||
IDirectInput8* GetDirectInput() {
|
||||
IDirectInput8 *GetDirectInput()
|
||||
{
|
||||
if (!di8d.lpDI8) {
|
||||
if (FAILED(DirectInput8Create(hInst, 0x800, IID_IDirectInput8, (void**) &di8d.lpDI8, 0))) return 0;
|
||||
if (FAILED(DirectInput8Create(hInst, 0x800, IID_IDirectInput8, (void **)&di8d.lpDI8, 0)))
|
||||
return 0;
|
||||
}
|
||||
di8d.refCount++;
|
||||
return di8d.lpDI8;
|
||||
}
|
||||
void ReleaseDirectInput() {
|
||||
void ReleaseDirectInput()
|
||||
{
|
||||
if (di8d.refCount) {
|
||||
di8d.refCount--;
|
||||
if (!di8d.refCount) {
|
||||
|
@ -78,42 +91,48 @@ void ReleaseDirectInput() {
|
|||
}
|
||||
}
|
||||
|
||||
static int StringToGUID(GUID *pg, wchar_t *dataw) {
|
||||
static int StringToGUID(GUID *pg, wchar_t *dataw)
|
||||
{
|
||||
char data[100];
|
||||
if (wcslen(dataw) > 50) return 0;
|
||||
if (wcslen(dataw) > 50)
|
||||
return 0;
|
||||
int w = 0;
|
||||
while (dataw[w]) {
|
||||
data[w] = (char) dataw[w];
|
||||
data[w] = (char)dataw[w];
|
||||
w++;
|
||||
}
|
||||
data[w] = 0;
|
||||
u32 temp[5];
|
||||
sscanf(data, "%08X-%04X-%04X-%04X-%04X%08X",
|
||||
&pg->Data1, temp, temp+1,
|
||||
temp+2, temp+3, temp+4);
|
||||
pg->Data2 = (u16) temp[0];
|
||||
pg->Data3 = (u16) temp[1];
|
||||
((u16*)pg->Data4)[0] = flipShort((u16)temp[2]);
|
||||
((u16*)pg->Data4)[1] = flipShort((u16)temp[3]);
|
||||
((u32*)pg->Data4)[1] = flipLong(temp[4]);
|
||||
&pg->Data1, temp, temp + 1,
|
||||
temp + 2, temp + 3, temp + 4);
|
||||
pg->Data2 = (u16)temp[0];
|
||||
pg->Data3 = (u16)temp[1];
|
||||
((u16 *)pg->Data4)[0] = flipShort((u16)temp[2]);
|
||||
((u16 *)pg->Data4)[1] = flipShort((u16)temp[3]);
|
||||
((u32 *)pg->Data4)[1] = flipLong(temp[4]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct DI8Effect {
|
||||
struct DI8Effect
|
||||
{
|
||||
IDirectInputEffect *die;
|
||||
int scale;
|
||||
};
|
||||
|
||||
BOOL CALLBACK EnumDeviceObjectsCallback (LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef);
|
||||
BOOL CALLBACK EnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef);
|
||||
BOOL CALLBACK EnumEffectsCallback(LPCDIEFFECTINFOW pdei, LPVOID pvRef);
|
||||
class DirectInputDevice : public Device {
|
||||
class DirectInputDevice : public Device
|
||||
{
|
||||
public:
|
||||
DI8Effect *diEffects;
|
||||
|
||||
IDirectInputDevice8 *did;
|
||||
GUID guidInstance;
|
||||
DirectInputDevice(DeviceType type, IDirectInputDevice8* did, wchar_t *displayName, wchar_t *instanceID, wchar_t *productID, GUID guid) : Device(DI, type, displayName, instanceID, productID) {
|
||||
DirectInputDevice(DeviceType type, IDirectInputDevice8 *did, wchar_t *displayName, wchar_t *instanceID, wchar_t *productID, GUID guid)
|
||||
: Device(DI, type, displayName, instanceID, productID)
|
||||
{
|
||||
diEffects = 0;
|
||||
guidInstance = guid;
|
||||
this->did = 0;
|
||||
|
@ -122,13 +141,14 @@ public:
|
|||
did->Release();
|
||||
}
|
||||
|
||||
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {
|
||||
void SetEffect(ForceFeedbackBinding *binding, unsigned char force)
|
||||
{
|
||||
int index = 0;
|
||||
if (!diEffects) {
|
||||
return;
|
||||
}
|
||||
for (int port=0; port<2; port++) {
|
||||
for (int slot=0; slot<4; slot++) {
|
||||
for (int port = 0; port < 2; port++) {
|
||||
for (int slot = 0; slot < 4; slot++) {
|
||||
unsigned int diff = binding - pads[port][slot].ffBindings;
|
||||
if (diff < (unsigned int)pads[port][slot].numFFBindings) {
|
||||
index += diff;
|
||||
|
@ -142,7 +162,8 @@ public:
|
|||
if (die) {
|
||||
DIEFFECT dieffect;
|
||||
memset(&dieffect, 0, sizeof(dieffect));
|
||||
union {
|
||||
union
|
||||
{
|
||||
DIPERIODIC periodic;
|
||||
DIRAMPFORCE ramp;
|
||||
DICONSTANTFORCE constant;
|
||||
|
@ -150,21 +171,20 @@ public:
|
|||
|
||||
dieffect.dwSize = sizeof(dieffect);
|
||||
dieffect.lpvTypeSpecificParams = &periodic;
|
||||
int magnitude = abs((int)((force*10000*(__int64)diEffects[index].scale)/BASE_SENSITIVITY/255));
|
||||
if (magnitude > 10000) magnitude = 10000;
|
||||
int magnitude = abs((int)((force * 10000 * (__int64)diEffects[index].scale) / BASE_SENSITIVITY / 255));
|
||||
if (magnitude > 10000)
|
||||
magnitude = 10000;
|
||||
int type = ffEffectTypes[binding->effectIndex].type;
|
||||
if (type == EFFECT_CONSTANT) {
|
||||
dieffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
||||
constant.lMagnitude = magnitude;
|
||||
}
|
||||
else if (type == EFFECT_PERIODIC) {
|
||||
} else if (type == EFFECT_PERIODIC) {
|
||||
dieffect.cbTypeSpecificParams = sizeof(DIPERIODIC);
|
||||
periodic.dwMagnitude = 0;
|
||||
periodic.lOffset = magnitude;
|
||||
periodic.dwPhase = 0;
|
||||
periodic.dwPeriod = 2000000;
|
||||
}
|
||||
else if (type == EFFECT_RAMP) {
|
||||
} else if (type == EFFECT_RAMP) {
|
||||
dieffect.cbTypeSpecificParams = sizeof(DIRAMPFORCE);
|
||||
ramp.lEnd = ramp.lStart = magnitude;
|
||||
}
|
||||
|
@ -174,11 +194,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
int Activate(InitInfo *initInfo) {
|
||||
int Activate(InitInfo *initInfo)
|
||||
{
|
||||
int i;
|
||||
IDirectInput8 *di8 = GetDirectInput();
|
||||
Deactivate();
|
||||
if (!di8) return 0;
|
||||
if (!di8)
|
||||
return 0;
|
||||
if (DI_OK != di8->CreateDevice(guidInstance, &did, 0)) {
|
||||
ReleaseDirectInput();
|
||||
did = 0;
|
||||
|
@ -186,10 +208,10 @@ public:
|
|||
}
|
||||
|
||||
{
|
||||
DIOBJECTDATAFORMAT *formats = (DIOBJECTDATAFORMAT*)calloc(numPhysicalControls, sizeof(DIOBJECTDATAFORMAT));
|
||||
for (i=0; i<numPhysicalControls; i++) {
|
||||
DIOBJECTDATAFORMAT *formats = (DIOBJECTDATAFORMAT *)calloc(numPhysicalControls, sizeof(DIOBJECTDATAFORMAT));
|
||||
for (i = 0; i < numPhysicalControls; i++) {
|
||||
formats[i].dwType = physicalControls[i].type | DIDFT_MAKEINSTANCE(physicalControls[i].id);
|
||||
formats[i].dwOfs = 4*i;
|
||||
formats[i].dwOfs = 4 * i;
|
||||
}
|
||||
DIDATAFORMAT format;
|
||||
format.dwSize = sizeof(format);
|
||||
|
@ -199,7 +221,7 @@ public:
|
|||
format.dwNumObjs = numPhysicalControls;
|
||||
format.rgodf = formats;
|
||||
int res = did->SetDataFormat(&format);
|
||||
for (i=0; i<numPhysicalControls; i++) {
|
||||
for (i = 0; i < numPhysicalControls; i++) {
|
||||
if (physicalControls[i].type == ABSAXIS) {
|
||||
DIPROPRANGE prop;
|
||||
prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
|
@ -230,11 +252,9 @@ public:
|
|||
// Note: Have to use hWndTop to properly hide cursor for mouse device.
|
||||
if (type == OTHER) {
|
||||
did->SetCooperativeLevel(initInfo->hWndTop, DISCL_BACKGROUND | DISCL_EXCLUSIVE);
|
||||
}
|
||||
else if (type == KEYBOARD) {
|
||||
} else if (type == KEYBOARD) {
|
||||
did->SetCooperativeLevel(initInfo->hWndTop, DISCL_FOREGROUND);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
did->SetCooperativeLevel(initInfo->hWndTop, DISCL_FOREGROUND | DISCL_EXCLUSIVE);
|
||||
}
|
||||
if (did->Acquire() != DI_OK) {
|
||||
|
@ -245,17 +265,18 @@ public:
|
|||
}
|
||||
AllocState();
|
||||
int count = GetFFBindingCount();
|
||||
diEffects = (DI8Effect*) calloc(count, sizeof(DI8Effect));
|
||||
diEffects = (DI8Effect *)calloc(count, sizeof(DI8Effect));
|
||||
i = 0;
|
||||
for (int port=0; port<2; port++) {
|
||||
for (int slot=0; slot<4; slot++) {
|
||||
for (int port = 0; port < 2; port++) {
|
||||
for (int slot = 0; slot < 4; slot++) {
|
||||
int subIndex = i;
|
||||
for (int j=0; j<pads[port][slot].numFFBindings; j++) {
|
||||
for (int j = 0; j < pads[port][slot].numFFBindings; j++) {
|
||||
ForceFeedbackBinding *b = 0;
|
||||
b = &pads[port][slot].ffBindings[i-subIndex];
|
||||
b = &pads[port][slot].ffBindings[i - subIndex];
|
||||
ForceFeedbackEffectType *eff = ffEffectTypes + b->effectIndex;
|
||||
GUID guid;
|
||||
if (!StringToGUID(&guid, eff->effectID)) continue;
|
||||
if (!StringToGUID(&guid, eff->effectID))
|
||||
continue;
|
||||
|
||||
DIEFFECT dieffect;
|
||||
memset(&dieffect, 0, sizeof(dieffect));
|
||||
|
@ -264,31 +285,30 @@ public:
|
|||
dieffect.dwDuration = 1000000;
|
||||
dieffect.dwGain = 10000;
|
||||
dieffect.dwTriggerButton = DIEB_NOTRIGGER;
|
||||
union {
|
||||
union
|
||||
{
|
||||
DIPERIODIC pediodic;
|
||||
DIRAMPFORCE ramp;
|
||||
DICONSTANTFORCE constant;
|
||||
} stuff = {0,0,0,0};
|
||||
} stuff = {0, 0, 0, 0};
|
||||
|
||||
if (eff->type == EFFECT_CONSTANT) {
|
||||
dieffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
||||
}
|
||||
else if (eff->type == EFFECT_PERIODIC) {
|
||||
} else if (eff->type == EFFECT_PERIODIC) {
|
||||
dieffect.cbTypeSpecificParams = sizeof(DIPERIODIC);
|
||||
}
|
||||
else if (eff->type == EFFECT_RAMP) {
|
||||
} else if (eff->type == EFFECT_RAMP) {
|
||||
dieffect.cbTypeSpecificParams = sizeof(DIRAMPFORCE);
|
||||
}
|
||||
dieffect.lpvTypeSpecificParams = &stuff;
|
||||
|
||||
int maxForce = 0;
|
||||
int numAxes = 0;
|
||||
int *axes = (int*) malloc(sizeof(int) * 3 * numFFAxes);
|
||||
DWORD *axisIDs = (DWORD*)(axes + numFFAxes);
|
||||
LONG *dirList = (LONG*)(axisIDs + numFFAxes);
|
||||
int *axes = (int *)malloc(sizeof(int) * 3 * numFFAxes);
|
||||
DWORD *axisIDs = (DWORD *)(axes + numFFAxes);
|
||||
LONG *dirList = (LONG *)(axisIDs + numFFAxes);
|
||||
dieffect.rgdwAxes = axisIDs;
|
||||
dieffect.rglDirection = dirList;
|
||||
for (int k=0; k<numFFAxes; k++) {
|
||||
for (int k = 0; k < numFFAxes; k++) {
|
||||
if (b->axes[k].force) {
|
||||
int force = abs(b->axes[k].force);
|
||||
if (force > maxForce) {
|
||||
|
@ -321,43 +341,46 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
int Update() {
|
||||
if (!active) return 0;
|
||||
int Update()
|
||||
{
|
||||
if (!active)
|
||||
return 0;
|
||||
if (numPhysicalControls) {
|
||||
HRESULT res = did->Poll();
|
||||
// ??
|
||||
if ((res != DI_OK && res != DI_NOEFFECT) ||
|
||||
DI_OK != did->GetDeviceState(4*numPhysicalControls, physicalControlState)) {
|
||||
DI_OK != did->GetDeviceState(4 * numPhysicalControls, physicalControlState)) {
|
||||
Deactivate();
|
||||
return 0;
|
||||
}
|
||||
for (int i=0; i<numPhysicalControls; i++) {
|
||||
for (int i = 0; i < numPhysicalControls; i++) {
|
||||
if (physicalControls[i].type & RELAXIS) {
|
||||
physicalControlState[i] *= (FULLY_DOWN/3);
|
||||
}
|
||||
else if (physicalControls[i].type & BUTTON) {
|
||||
physicalControlState[i] = (physicalControlState[i]&0x80) * FULLY_DOWN / 128;
|
||||
physicalControlState[i] *= (FULLY_DOWN / 3);
|
||||
} else if (physicalControls[i].type & BUTTON) {
|
||||
physicalControlState[i] = (physicalControlState[i] & 0x80) * FULLY_DOWN / 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetFFBindingCount() {
|
||||
int GetFFBindingCount()
|
||||
{
|
||||
int count = 0;
|
||||
for (int port = 0; port<2; port++) {
|
||||
for (int slot = 0; slot<4; slot++) {
|
||||
for (int port = 0; port < 2; port++) {
|
||||
for (int slot = 0; slot < 4; slot++) {
|
||||
count += pads[port][slot].numFFBindings;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void Deactivate() {
|
||||
void Deactivate()
|
||||
{
|
||||
FreeState();
|
||||
if (diEffects) {
|
||||
int count = GetFFBindingCount();
|
||||
for (int i=0; i<count; i++) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (diEffects[i].die) {
|
||||
diEffects[i].die->Stop();
|
||||
diEffects[i].die->Release();
|
||||
|
@ -375,24 +398,23 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
~DirectInputDevice() {
|
||||
~DirectInputDevice()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
BOOL CALLBACK EnumEffectsCallback(LPCDIEFFECTINFOW pdei, LPVOID pvRef) {
|
||||
DirectInputDevice * did = (DirectInputDevice*) pvRef;
|
||||
BOOL CALLBACK EnumEffectsCallback(LPCDIEFFECTINFOW pdei, LPVOID pvRef)
|
||||
{
|
||||
DirectInputDevice *did = (DirectInputDevice *)pvRef;
|
||||
EffectType type;
|
||||
int diType = DIEFT_GETTYPE(pdei->dwEffType);
|
||||
if (diType == DIEFT_CONSTANTFORCE) {
|
||||
type = EFFECT_CONSTANT;
|
||||
}
|
||||
else if (diType == DIEFT_RAMPFORCE) {
|
||||
} else if (diType == DIEFT_RAMPFORCE) {
|
||||
type = EFFECT_RAMP;
|
||||
}
|
||||
else if (diType == DIEFT_PERIODIC) {
|
||||
} else if (diType == DIEFT_PERIODIC) {
|
||||
type = EFFECT_PERIODIC;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
wchar_t guidString[50];
|
||||
|
@ -402,8 +424,9 @@ BOOL CALLBACK EnumEffectsCallback(LPCDIEFFECTINFOW pdei, LPVOID pvRef) {
|
|||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
BOOL CALLBACK EnumDeviceObjectsCallback (LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) {
|
||||
DirectInputDevice * did = (DirectInputDevice*) pvRef;
|
||||
BOOL CALLBACK EnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef)
|
||||
{
|
||||
DirectInputDevice *did = (DirectInputDevice *)pvRef;
|
||||
if (lpddoi->dwType & DIDFT_FFACTUATOR) {
|
||||
did->AddFFAxis(lpddoi->tszName, lpddoi->dwType);
|
||||
}
|
||||
|
@ -425,8 +448,9 @@ BOOL CALLBACK EnumDeviceObjectsCallback (LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOI
|
|||
// If too many objects, ignore extra buttons.
|
||||
if ((did->numPhysicalControls > 255 && DIDFT_GETINSTANCE(lpddoi->dwType) > 255) && (type & (DIDFT_PSHBUTTON | DIDFT_TGLBUTTON))) {
|
||||
int i;
|
||||
for (i = did->numPhysicalControls-1; i>did->numPhysicalControls-4; i--) {
|
||||
if (!lpddoi->tszName[0]) break;
|
||||
for (i = did->numPhysicalControls - 1; i > did->numPhysicalControls - 4; i--) {
|
||||
if (!lpddoi->tszName[0])
|
||||
break;
|
||||
const wchar_t *s1 = lpddoi->tszName;
|
||||
const wchar_t *s2 = did->physicalControls[i].name;
|
||||
while (*s1 && *s1 == *s2) {
|
||||
|
@ -434,12 +458,14 @@ BOOL CALLBACK EnumDeviceObjectsCallback (LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOI
|
|||
s2++;
|
||||
}
|
||||
// If perfect match with one of last 4 names, break.
|
||||
if (!*s1 && !*s2) break;
|
||||
if (!*s1 && !*s2)
|
||||
break;
|
||||
|
||||
while (s1 != lpddoi->tszName && (s1[-1] >= '0' && s1[-1] <= '9')) s1--;
|
||||
while (s1 != lpddoi->tszName && (s1[-1] >= '0' && s1[-1] <= '9'))
|
||||
s1--;
|
||||
int check = 0;
|
||||
while (*s1 >= '0' && *s1 <= '9') {
|
||||
check = check*10 + *s1 - '0';
|
||||
check = check * 10 + *s1 - '0';
|
||||
s1++;
|
||||
}
|
||||
while (*s2 >= '0' && *s2 <= '9') {
|
||||
|
@ -447,16 +473,17 @@ BOOL CALLBACK EnumDeviceObjectsCallback (LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOI
|
|||
}
|
||||
// If perfect match other than final number > 30, then break.
|
||||
// takes care of "button xx" case without causing issues with F keys.
|
||||
if (!*s1 && !*s2 && check > 30) break;
|
||||
if (!*s1 && !*s2 && check > 30)
|
||||
break;
|
||||
}
|
||||
if (i != did->numPhysicalControls-4) {
|
||||
if (i != did->numPhysicalControls - 4) {
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
int vkey = 0;
|
||||
if (lpddoi->tszName[0] && did->type == KEYBOARD) {
|
||||
for (u32 i = 0; i<256; i++) {
|
||||
for (u32 i = 0; i < 256; i++) {
|
||||
wchar_t *t = GetVKStringW((u8)i);
|
||||
if (!wcsicmp(lpddoi->tszName, t)) {
|
||||
vkey = i;
|
||||
|
@ -470,17 +497,17 @@ BOOL CALLBACK EnumDeviceObjectsCallback (LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOI
|
|||
|
||||
// Evil code from MS's site. If only they'd just made a way to get
|
||||
// an XInput device's GUID directly in the first place...
|
||||
BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput )
|
||||
BOOL IsXInputDevice(const GUID *pGuidProductFromDirectInput)
|
||||
{
|
||||
IWbemLocator* pIWbemLocator = NULL;
|
||||
IEnumWbemClassObject* pEnumDevices = NULL;
|
||||
IWbemClassObject* pDevices[20] = {0};
|
||||
IWbemServices* pIWbemServices = NULL;
|
||||
IWbemLocator *pIWbemLocator = NULL;
|
||||
IEnumWbemClassObject *pEnumDevices = NULL;
|
||||
IWbemClassObject *pDevices[20] = {0};
|
||||
IWbemServices *pIWbemServices = NULL;
|
||||
BSTR bstrNamespace = NULL;
|
||||
BSTR bstrDeviceID = NULL;
|
||||
BSTR bstrClassName = NULL;
|
||||
DWORD uReturned = 0;
|
||||
bool bIsXinputDevice= false;
|
||||
bool bIsXinputDevice = false;
|
||||
UINT iDevice = 0;
|
||||
VARIANT var;
|
||||
HRESULT hr;
|
||||
|
@ -490,118 +517,119 @@ BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput )
|
|||
bool bCleanupCOM = SUCCEEDED(hr);
|
||||
|
||||
// Create WMI
|
||||
hr = CoCreateInstance( __uuidof(WbemLocator),
|
||||
hr = CoCreateInstance(__uuidof(WbemLocator),
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWbemLocator),
|
||||
(LPVOID*) &pIWbemLocator);
|
||||
if( FAILED(hr) || pIWbemLocator == NULL )
|
||||
(LPVOID *)&pIWbemLocator);
|
||||
if (FAILED(hr) || pIWbemLocator == NULL)
|
||||
goto LCleanup;
|
||||
|
||||
bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );if( bstrNamespace == NULL ) goto LCleanup;
|
||||
bstrClassName = SysAllocString( L"Win32_PNPEntity" ); if( bstrClassName == NULL ) goto LCleanup;
|
||||
bstrDeviceID = SysAllocString( L"DeviceID" ); if( bstrDeviceID == NULL ) goto LCleanup;
|
||||
bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2");
|
||||
if (bstrNamespace == NULL)
|
||||
goto LCleanup;
|
||||
bstrClassName = SysAllocString(L"Win32_PNPEntity");
|
||||
if (bstrClassName == NULL)
|
||||
goto LCleanup;
|
||||
bstrDeviceID = SysAllocString(L"DeviceID");
|
||||
if (bstrDeviceID == NULL)
|
||||
goto LCleanup;
|
||||
|
||||
// Connect to WMI
|
||||
hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L,
|
||||
0L, NULL, NULL, &pIWbemServices );
|
||||
if( FAILED(hr) || pIWbemServices == NULL )
|
||||
hr = pIWbemLocator->ConnectServer(bstrNamespace, NULL, NULL, 0L,
|
||||
0L, NULL, NULL, &pIWbemServices);
|
||||
if (FAILED(hr) || pIWbemServices == NULL)
|
||||
goto LCleanup;
|
||||
|
||||
// Switch security level to IMPERSONATE.
|
||||
CoSetProxyBlanket( pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
|
||||
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
|
||||
CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
|
||||
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
|
||||
|
||||
hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices );
|
||||
if( FAILED(hr) || pEnumDevices == NULL )
|
||||
hr = pIWbemServices->CreateInstanceEnum(bstrClassName, 0, NULL, &pEnumDevices);
|
||||
if (FAILED(hr) || pEnumDevices == NULL)
|
||||
goto LCleanup;
|
||||
|
||||
// Loop over all devices
|
||||
for( ;; )
|
||||
{
|
||||
for (;;) {
|
||||
// Get 20 at a time
|
||||
hr = pEnumDevices->Next( 10000, 20, pDevices, &uReturned );
|
||||
if( FAILED(hr) )
|
||||
hr = pEnumDevices->Next(10000, 20, pDevices, &uReturned);
|
||||
if (FAILED(hr))
|
||||
goto LCleanup;
|
||||
if( uReturned == 0 )
|
||||
if (uReturned == 0)
|
||||
break;
|
||||
|
||||
for( iDevice=0; iDevice<uReturned; iDevice++ )
|
||||
{
|
||||
for (iDevice = 0; iDevice < uReturned; iDevice++) {
|
||||
// For each device, get its device ID
|
||||
hr = pDevices[iDevice]->Get( bstrDeviceID, 0L, &var, NULL, NULL );
|
||||
if( SUCCEEDED( hr ) && var.vt == VT_BSTR && var.bstrVal != NULL )
|
||||
{
|
||||
hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, NULL, NULL);
|
||||
if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL) {
|
||||
// Check if the device ID contains "IG_". If it does, then it's an XInput device
|
||||
// This information can not be found from DirectInput
|
||||
if( wcsstr( var.bstrVal, L"IG_" ) )
|
||||
{
|
||||
if (wcsstr(var.bstrVal, L"IG_")) {
|
||||
// If it does, then get the VID/PID from var.bstrVal
|
||||
DWORD dwPid = 0, dwVid = 0;
|
||||
WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" );
|
||||
WCHAR *strVid = wcsstr(var.bstrVal, L"VID_");
|
||||
if (strVid) {
|
||||
dwVid = wcstoul(strVid+4, 0, 16);
|
||||
dwVid = wcstoul(strVid + 4, 0, 16);
|
||||
}
|
||||
WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" );
|
||||
WCHAR *strPid = wcsstr(var.bstrVal, L"PID_");
|
||||
if (strPid) {
|
||||
dwPid = wcstoul(strPid+4, 0, 16);
|
||||
dwPid = wcstoul(strPid + 4, 0, 16);
|
||||
}
|
||||
|
||||
// Compare the VID/PID to the DInput device
|
||||
DWORD dwVidPid = MAKELONG( dwVid, dwPid );
|
||||
if( dwVidPid == pGuidProductFromDirectInput->Data1 )
|
||||
{
|
||||
DWORD dwVidPid = MAKELONG(dwVid, dwPid);
|
||||
if (dwVidPid == pGuidProductFromDirectInput->Data1) {
|
||||
bIsXinputDevice = true;
|
||||
goto LCleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_RELEASE( pDevices[iDevice] );
|
||||
SAFE_RELEASE(pDevices[iDevice]);
|
||||
}
|
||||
}
|
||||
|
||||
LCleanup:
|
||||
if(bstrNamespace)
|
||||
if (bstrNamespace)
|
||||
SysFreeString(bstrNamespace);
|
||||
if(bstrDeviceID)
|
||||
if (bstrDeviceID)
|
||||
SysFreeString(bstrDeviceID);
|
||||
if(bstrClassName)
|
||||
if (bstrClassName)
|
||||
SysFreeString(bstrClassName);
|
||||
for( iDevice=0; iDevice<20; iDevice++ )
|
||||
SAFE_RELEASE( pDevices[iDevice] );
|
||||
SAFE_RELEASE( pEnumDevices );
|
||||
SAFE_RELEASE( pIWbemLocator );
|
||||
SAFE_RELEASE( pIWbemServices );
|
||||
for (iDevice = 0; iDevice < 20; iDevice++)
|
||||
SAFE_RELEASE(pDevices[iDevice]);
|
||||
SAFE_RELEASE(pEnumDevices);
|
||||
SAFE_RELEASE(pIWbemLocator);
|
||||
SAFE_RELEASE(pIWbemServices);
|
||||
|
||||
if( bCleanupCOM )
|
||||
if (bCleanupCOM)
|
||||
CoUninitialize();
|
||||
|
||||
return bIsXinputDevice;
|
||||
}
|
||||
|
||||
|
||||
struct DeviceEnumInfo {
|
||||
struct DeviceEnumInfo
|
||||
{
|
||||
IDirectInput8 *di8;
|
||||
int ignoreXInput;
|
||||
};
|
||||
|
||||
BOOL CALLBACK EnumCallback (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) {
|
||||
IDirectInput8* di8 = ((DeviceEnumInfo*)pvRef)->di8;
|
||||
BOOL CALLBACK EnumCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
|
||||
{
|
||||
IDirectInput8 *di8 = ((DeviceEnumInfo *)pvRef)->di8;
|
||||
const wchar_t *name;
|
||||
wchar_t temp[40];
|
||||
//if (((DeviceEnumInfo*)pvRef)->ignoreXInput && lpddi->
|
||||
if (lpddi->tszInstanceName[0]) {
|
||||
name = lpddi->tszInstanceName;
|
||||
}
|
||||
else if (lpddi->tszProductName[0]) {
|
||||
} else if (lpddi->tszProductName[0]) {
|
||||
name = lpddi->tszProductName;
|
||||
}
|
||||
else {
|
||||
wsprintfW (temp, L"Device %i", di8d.deviceCount);
|
||||
} else {
|
||||
wsprintfW(temp, L"Device %i", di8d.deviceCount);
|
||||
name = temp;
|
||||
}
|
||||
di8d.deviceCount++;
|
||||
wchar_t *fullName = (wchar_t *) malloc((wcslen(name) + 4) * sizeof(wchar_t));
|
||||
wchar_t *fullName = (wchar_t *)malloc((wcslen(name) + 4) * sizeof(wchar_t));
|
||||
wsprintf(fullName, L"DX %s", name);
|
||||
wchar_t instanceID[100];
|
||||
wchar_t productID[100];
|
||||
|
@ -610,8 +638,7 @@ BOOL CALLBACK EnumCallback (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) {
|
|||
DeviceType type = OTHER;
|
||||
if ((lpddi->dwDevType & 0xFF) == DI8DEVTYPE_KEYBOARD) {
|
||||
type = KEYBOARD;
|
||||
}
|
||||
else if ((lpddi->dwDevType & 0xFF) == DI8DEVTYPE_MOUSE) {
|
||||
} else if ((lpddi->dwDevType & 0xFF) == DI8DEVTYPE_MOUSE) {
|
||||
type = MOUSE;
|
||||
}
|
||||
IDirectInputDevice8 *did;
|
||||
|
@ -619,8 +646,7 @@ BOOL CALLBACK EnumCallback (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) {
|
|||
DirectInputDevice *dev = new DirectInputDevice(type, did, fullName, instanceID, productID, lpddi->guidInstance);
|
||||
if (dev->numPhysicalControls || dev->numFFAxes) {
|
||||
dm->AddDevice(dev);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
delete dev;
|
||||
}
|
||||
}
|
||||
|
@ -628,13 +654,14 @@ BOOL CALLBACK EnumCallback (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) {
|
|||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
void EnumDirectInputDevices(int ignoreXInput) {
|
||||
void EnumDirectInputDevices(int ignoreXInput)
|
||||
{
|
||||
DeviceEnumInfo enumInfo;
|
||||
enumInfo.di8 = GetDirectInput();
|
||||
if (!enumInfo.di8) return;
|
||||
if (!enumInfo.di8)
|
||||
return;
|
||||
enumInfo.ignoreXInput = ignoreXInput;
|
||||
di8d.deviceCount = 0;
|
||||
enumInfo.di8->EnumDevices(DI8DEVCLASS_ALL, EnumCallback, &enumInfo, DIEDFL_ATTACHEDONLY);
|
||||
ReleaseDirectInput();
|
||||
}
|
||||
|
||||
|
|
|
@ -41,15 +41,15 @@
|
|||
unsigned int lastDS3Check = 0;
|
||||
unsigned int lastDS3Enum = 0;
|
||||
|
||||
typedef void (__cdecl *_usb_init)(void);
|
||||
typedef int (__cdecl *_usb_close)(usb_dev_handle *dev);
|
||||
typedef int (__cdecl *_usb_get_string_simple)(usb_dev_handle *dev, int index, char *buf, size_t buflen);
|
||||
typedef void(__cdecl *_usb_init)(void);
|
||||
typedef int(__cdecl *_usb_close)(usb_dev_handle *dev);
|
||||
typedef int(__cdecl *_usb_get_string_simple)(usb_dev_handle *dev, int index, char *buf, size_t buflen);
|
||||
typedef usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev);
|
||||
typedef int (__cdecl *_usb_find_busses)(void);
|
||||
typedef int (__cdecl *_usb_find_devices)(void);
|
||||
typedef int(__cdecl *_usb_find_busses)(void);
|
||||
typedef int(__cdecl *_usb_find_devices)(void);
|
||||
typedef struct usb_bus *(__cdecl *_usb_get_busses)(void);
|
||||
typedef usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev);
|
||||
typedef int (__cdecl *_usb_control_msg)(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
|
||||
typedef int(__cdecl *_usb_control_msg)(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
|
||||
|
||||
_usb_init pusb_init;
|
||||
_usb_close pusb_close;
|
||||
|
@ -62,14 +62,16 @@ _usb_control_msg pusb_control_msg;
|
|||
|
||||
HMODULE hModLibusb = 0;
|
||||
|
||||
void UninitLibUsb() {
|
||||
void UninitLibUsb()
|
||||
{
|
||||
if (hModLibusb) {
|
||||
FreeLibrary(hModLibusb);
|
||||
hModLibusb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TryInitDS3(usb_device *dev) {
|
||||
void TryInitDS3(usb_device *dev)
|
||||
{
|
||||
while (dev) {
|
||||
if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID) {
|
||||
usb_dev_handle *handle = pusb_open(dev);
|
||||
|
@ -82,7 +84,7 @@ void TryInitDS3(usb_device *dev) {
|
|||
}
|
||||
}
|
||||
if (dev->num_children) {
|
||||
for (int i=0; i<dev->num_children; i++) {
|
||||
for (int i = 0; i < dev->num_children; i++) {
|
||||
TryInitDS3(dev->children[i]);
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +92,8 @@ void TryInitDS3(usb_device *dev) {
|
|||
}
|
||||
}
|
||||
|
||||
void DS3Enum(unsigned int time) {
|
||||
void DS3Enum(unsigned int time)
|
||||
{
|
||||
if (time - lastDS3Enum < DOUBLE_ENUM_DELAY) {
|
||||
return;
|
||||
}
|
||||
|
@ -99,7 +102,8 @@ void DS3Enum(unsigned int time) {
|
|||
pusb_find_devices();
|
||||
}
|
||||
|
||||
void DS3Check(unsigned int time) {
|
||||
void DS3Check(unsigned int time)
|
||||
{
|
||||
if (time - lastDS3Check < DOUBLE_CHECK_DELAY) {
|
||||
return;
|
||||
}
|
||||
|
@ -115,20 +119,21 @@ void DS3Check(unsigned int time) {
|
|||
}
|
||||
}
|
||||
|
||||
int InitLibUsb() {
|
||||
int InitLibUsb()
|
||||
{
|
||||
if (hModLibusb) {
|
||||
return 1;
|
||||
}
|
||||
hModLibusb = LoadLibraryA("C:\\windows\\system32\\libusb0.dll");
|
||||
if (hModLibusb) {
|
||||
if ((pusb_init = (_usb_init) GetProcAddress(hModLibusb, "usb_init")) &&
|
||||
(pusb_close = (_usb_close) GetProcAddress(hModLibusb, "usb_close")) &&
|
||||
(pusb_get_string_simple = (_usb_get_string_simple) GetProcAddress(hModLibusb, "usb_get_string_simple")) &&
|
||||
(pusb_open = (_usb_open) GetProcAddress(hModLibusb, "usb_open")) &&
|
||||
(pusb_find_busses = (_usb_find_busses) GetProcAddress(hModLibusb, "usb_find_busses")) &&
|
||||
(pusb_find_devices = (_usb_find_devices) GetProcAddress(hModLibusb, "usb_find_devices")) &&
|
||||
(pusb_get_busses = (_usb_get_busses) GetProcAddress(hModLibusb, "usb_get_busses")) &&
|
||||
(pusb_control_msg = (_usb_control_msg) GetProcAddress(hModLibusb, "usb_control_msg"))) {
|
||||
if ((pusb_init = (_usb_init)GetProcAddress(hModLibusb, "usb_init")) &&
|
||||
(pusb_close = (_usb_close)GetProcAddress(hModLibusb, "usb_close")) &&
|
||||
(pusb_get_string_simple = (_usb_get_string_simple)GetProcAddress(hModLibusb, "usb_get_string_simple")) &&
|
||||
(pusb_open = (_usb_open)GetProcAddress(hModLibusb, "usb_open")) &&
|
||||
(pusb_find_busses = (_usb_find_busses)GetProcAddress(hModLibusb, "usb_find_busses")) &&
|
||||
(pusb_find_devices = (_usb_find_devices)GetProcAddress(hModLibusb, "usb_find_devices")) &&
|
||||
(pusb_get_busses = (_usb_get_busses)GetProcAddress(hModLibusb, "usb_get_busses")) &&
|
||||
(pusb_control_msg = (_usb_control_msg)GetProcAddress(hModLibusb, "usb_control_msg"))) {
|
||||
pusb_init();
|
||||
return 1;
|
||||
}
|
||||
|
@ -137,18 +142,21 @@ int InitLibUsb() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int DualShock3Possible() {
|
||||
int DualShock3Possible()
|
||||
{
|
||||
return InitLibUsb();
|
||||
}
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
struct MotorState {
|
||||
struct MotorState
|
||||
{
|
||||
unsigned char duration;
|
||||
unsigned char force;
|
||||
};
|
||||
|
||||
struct LightState {
|
||||
struct LightState
|
||||
{
|
||||
// 0xFF makes it stay on.
|
||||
unsigned char duration;
|
||||
// Have to make one or the other non-zero to turn on light.
|
||||
|
@ -160,7 +168,8 @@ struct LightState {
|
|||
};
|
||||
|
||||
// Data sent to DS3 to set state.
|
||||
struct DS3Command {
|
||||
struct DS3Command
|
||||
{
|
||||
unsigned char id;
|
||||
unsigned char unsure;
|
||||
// Small is first, then big.
|
||||
|
@ -175,21 +184,25 @@ struct DS3Command {
|
|||
|
||||
#include <poppack.h>
|
||||
|
||||
int CharToAxis(unsigned char c) {
|
||||
int CharToAxis(unsigned char c)
|
||||
{
|
||||
int v = (int)c + ((unsigned int)c >> 7);
|
||||
return ((c-128) * FULLY_DOWN)>>7;
|
||||
return ((c - 128) * FULLY_DOWN) >> 7;
|
||||
}
|
||||
|
||||
int CharToButton(unsigned char c) {
|
||||
int CharToButton(unsigned char c)
|
||||
{
|
||||
int v = (int)c + ((unsigned int)c >> 7);
|
||||
return (v * FULLY_DOWN)>>8;
|
||||
return (v * FULLY_DOWN) >> 8;
|
||||
}
|
||||
|
||||
class DualShock3Device : public Device {
|
||||
class DualShock3Device : public Device
|
||||
{
|
||||
// Cached last vibration values by pad and motor.
|
||||
// Need this, as only one value is changed at a time.
|
||||
int ps2Vibration[2][4][2];
|
||||
int vibration[2];
|
||||
|
||||
public:
|
||||
int index;
|
||||
HANDLE hFile;
|
||||
|
@ -205,12 +218,14 @@ public:
|
|||
int writeQueued;
|
||||
int writing;
|
||||
|
||||
int StartRead() {
|
||||
int StartRead()
|
||||
{
|
||||
int res = ReadFile(hFile, &getState, sizeof(getState), 0, &readop);
|
||||
return (res || GetLastError() == ERROR_IO_PENDING);
|
||||
}
|
||||
|
||||
void QueueWrite() {
|
||||
void QueueWrite()
|
||||
{
|
||||
// max of 2 queued writes allowed, one for either motor.
|
||||
if (writeQueued < 2) {
|
||||
writeQueued++;
|
||||
|
@ -218,7 +233,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
int StartWrite() {
|
||||
int StartWrite()
|
||||
{
|
||||
if (!writing && writeQueued) {
|
||||
lastWrite = GetTickCount();
|
||||
writing++;
|
||||
|
@ -226,14 +242,15 @@ public:
|
|||
sendState.motors[0].duration = 0x50;
|
||||
sendState.motors[1].duration = 0x50;
|
||||
|
||||
int bigForce = vibration[0] * 256/FULLY_DOWN;
|
||||
if (bigForce > 255) bigForce = 255;
|
||||
sendState.motors[1].force = (unsigned char) bigForce;
|
||||
sendState.motors[0].force = (unsigned char) (vibration[1] >= FULLY_DOWN/2);
|
||||
int bigForce = vibration[0] * 256 / FULLY_DOWN;
|
||||
if (bigForce > 255)
|
||||
bigForce = 255;
|
||||
sendState.motors[1].force = (unsigned char)bigForce;
|
||||
sendState.motors[0].force = (unsigned char)(vibration[1] >= FULLY_DOWN / 2);
|
||||
// Can't seem to have them both non-zero at once.
|
||||
if (sendState.motors[writeCount&1].force) {
|
||||
sendState.motors[(writeCount&1)^1].force = 0;
|
||||
sendState.motors[(writeCount&1)^1].duration = 0;
|
||||
if (sendState.motors[writeCount & 1].force) {
|
||||
sendState.motors[(writeCount & 1) ^ 1].force = 0;
|
||||
sendState.motors[(writeCount & 1) ^ 1].duration = 0;
|
||||
}
|
||||
|
||||
writeCount++;
|
||||
|
@ -243,7 +260,9 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
DualShock3Device(int index, wchar_t *name, wchar_t *path) : Device(DS3, OTHER, name, path, L"DualShock 3") {
|
||||
DualShock3Device(int index, wchar_t *name, wchar_t *path)
|
||||
: Device(DS3, OTHER, name, path, L"DualShock 3")
|
||||
{
|
||||
writeCount = 0;
|
||||
writing = 0;
|
||||
writeQueued = 0;
|
||||
|
@ -251,24 +270,23 @@ public:
|
|||
memset(&writeop, 0, sizeof(writeop));
|
||||
memset(&sendState, 0, sizeof(sendState));
|
||||
sendState.id = 1;
|
||||
int temp = (index&4);
|
||||
sendState.lightFlags = (1 << (temp+1));
|
||||
sendState.lights[3-temp].duration = 0xFF;
|
||||
sendState.lights[3-temp].dunno[0] = 1;
|
||||
sendState.lights[3-temp].on = 1;
|
||||
int temp = (index & 4);
|
||||
sendState.lightFlags = (1 << (temp + 1));
|
||||
sendState.lights[3 - temp].duration = 0xFF;
|
||||
sendState.lights[3 - temp].dunno[0] = 1;
|
||||
sendState.lights[3 - temp].on = 1;
|
||||
memset(ps2Vibration, 0, sizeof(ps2Vibration));
|
||||
vibration[0] = vibration[1] = 0;
|
||||
this->index = index;
|
||||
int i;
|
||||
for (i=0; i<16; i++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (i != 14 && i != 15 && i != 8 && i != 9) {
|
||||
AddPhysicalControl(PRESSURE_BTN, i, 0);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
AddPhysicalControl(PSHBTN, i, 0);
|
||||
}
|
||||
}
|
||||
for (; i<23; i++) {
|
||||
for (; i < 23; i++) {
|
||||
AddPhysicalControl(ABSAXIS, i, 0);
|
||||
}
|
||||
AddFFAxis(L"Big Motor", 0);
|
||||
|
@ -277,7 +295,8 @@ public:
|
|||
hFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
wchar_t *GetPhysicalControlName(PhysicalControl *c) {
|
||||
wchar_t *GetPhysicalControlName(PhysicalControl *c)
|
||||
{
|
||||
const static wchar_t *names[] = {
|
||||
L"Square",
|
||||
L"Cross",
|
||||
|
@ -303,15 +322,17 @@ public:
|
|||
L"Forward/Back Tilt",
|
||||
L"???",
|
||||
};
|
||||
unsigned int i = (unsigned int) (c - physicalControls);
|
||||
if (i < sizeof(names)/sizeof(names[0])) {
|
||||
return (wchar_t*)names[i];
|
||||
unsigned int i = (unsigned int)(c - physicalControls);
|
||||
if (i < sizeof(names) / sizeof(names[0])) {
|
||||
return (wchar_t *)names[i];
|
||||
}
|
||||
return Device::GetPhysicalControlName(c);
|
||||
}
|
||||
|
||||
int Activate(InitInfo *initInfo) {
|
||||
if (active) Deactivate();
|
||||
int Activate(InitInfo *initInfo)
|
||||
{
|
||||
if (active)
|
||||
Deactivate();
|
||||
// Give grace period before get mad.
|
||||
lastWrite = dataLastReceived = GetTickCount();
|
||||
readop.hEvent = CreateEvent(0, 0, 0, 0);
|
||||
|
@ -327,12 +348,13 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
int Update() {
|
||||
if (!active) return 0;
|
||||
int Update()
|
||||
{
|
||||
if (!active)
|
||||
return 0;
|
||||
HANDLE h[2] = {
|
||||
readop.hEvent,
|
||||
writeop.hEvent
|
||||
};
|
||||
writeop.hEvent};
|
||||
unsigned int time = GetTickCount();
|
||||
if (time - lastWrite > UPDATE_INTERVAL) {
|
||||
QueueWrite();
|
||||
|
@ -358,20 +380,19 @@ public:
|
|||
physicalControlState[11] = CharToButton(getState[16]);
|
||||
physicalControlState[12] = CharToButton(getState[15]);
|
||||
physicalControlState[13] = CharToButton(getState[14]);
|
||||
physicalControlState[8] = ((getState[2]&4)/4) * FULLY_DOWN;
|
||||
physicalControlState[9] = ((getState[2]&2)/2) * FULLY_DOWN;
|
||||
physicalControlState[15] = ((getState[2]&1)/1) * FULLY_DOWN;
|
||||
physicalControlState[14] = ((getState[2]&8)/8) * FULLY_DOWN;
|
||||
physicalControlState[8] = ((getState[2] & 4) / 4) * FULLY_DOWN;
|
||||
physicalControlState[9] = ((getState[2] & 2) / 2) * FULLY_DOWN;
|
||||
physicalControlState[15] = ((getState[2] & 1) / 1) * FULLY_DOWN;
|
||||
physicalControlState[14] = ((getState[2] & 8) / 8) * FULLY_DOWN;
|
||||
physicalControlState[16] = CharToAxis(getState[6]);
|
||||
physicalControlState[17] = CharToAxis(getState[7]);
|
||||
physicalControlState[18] = CharToAxis(getState[8]);
|
||||
physicalControlState[19] = CharToAxis(getState[9]);
|
||||
physicalControlState[20] = CharToAxis(getState[42]+128);
|
||||
physicalControlState[21] = CharToAxis(getState[44]+128);
|
||||
physicalControlState[22] = CharToAxis(getState[46]+128);
|
||||
physicalControlState[20] = CharToAxis(getState[42] + 128);
|
||||
physicalControlState[21] = CharToAxis(getState[44] + 128);
|
||||
physicalControlState[22] = CharToAxis(getState[46] + 128);
|
||||
continue;
|
||||
}
|
||||
else if (res == WAIT_OBJECT_0+1) {
|
||||
} else if (res == WAIT_OBJECT_0 + 1) {
|
||||
writing = 0;
|
||||
if (!writeQueued && (vibration[0] | vibration[1])) {
|
||||
QueueWrite();
|
||||
|
@ -380,10 +401,9 @@ public:
|
|||
Deactivate();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (time-dataLastReceived >= DEVICE_CHECK_DELAY) {
|
||||
if (time-dataLastReceived >= DEVICE_ENUM_DELAY) {
|
||||
} else {
|
||||
if (time - dataLastReceived >= DEVICE_CHECK_DELAY) {
|
||||
if (time - dataLastReceived >= DEVICE_ENUM_DELAY) {
|
||||
DS3Enum(time);
|
||||
}
|
||||
DS3Check(time);
|
||||
|
@ -395,12 +415,13 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) {
|
||||
void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force)
|
||||
{
|
||||
ps2Vibration[port][slot][motor] = force;
|
||||
vibration[0] = vibration[1] = 0;
|
||||
for (int p=0; p<2; p++) {
|
||||
for (int s=0; s<4; s++) {
|
||||
for (int i=0; i<pads[p][s].numFFBindings; i++) {
|
||||
for (int p = 0; p < 2; p++) {
|
||||
for (int s = 0; s < 4; s++) {
|
||||
for (int i = 0; i < pads[p][s].numFFBindings; i++) {
|
||||
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
|
||||
ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i];
|
||||
vibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
|
||||
|
@ -413,7 +434,8 @@ public:
|
|||
QueueWrite();
|
||||
}
|
||||
|
||||
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {
|
||||
void SetEffect(ForceFeedbackBinding *binding, unsigned char force)
|
||||
{
|
||||
PadBindings pBackup = pads[0][0];
|
||||
pads[0][0].ffBindings = binding;
|
||||
pads[0][0].numFFBindings = 1;
|
||||
|
@ -421,7 +443,8 @@ public:
|
|||
pads[0][0] = pBackup;
|
||||
}
|
||||
|
||||
void Deactivate() {
|
||||
void Deactivate()
|
||||
{
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
CancelIo(hFile);
|
||||
CloseHandle(hFile);
|
||||
|
@ -442,24 +465,28 @@ public:
|
|||
active = 0;
|
||||
}
|
||||
|
||||
~DualShock3Device() {
|
||||
~DualShock3Device()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void EnumDualShock3s() {
|
||||
if (!InitLibUsb()) return;
|
||||
void EnumDualShock3s()
|
||||
{
|
||||
if (!InitLibUsb())
|
||||
return;
|
||||
|
||||
HidDeviceInfo *foundDevs = 0;
|
||||
|
||||
int numDevs = FindHids(&foundDevs, VID, PID);
|
||||
if (!numDevs) return;
|
||||
if (!numDevs)
|
||||
return;
|
||||
int index = 0;
|
||||
for (int i=0; i<numDevs; i++) {
|
||||
for (int i = 0; i < numDevs; i++) {
|
||||
if (foundDevs[i].caps.FeatureReportByteLength == 49 &&
|
||||
foundDevs[i].caps.InputReportByteLength == 49 &&
|
||||
foundDevs[i].caps.OutputReportByteLength == 49) {
|
||||
wchar_t temp[100];
|
||||
wsprintfW(temp, L"DualShock 3 #%i", index+1);
|
||||
wsprintfW(temp, L"DualShock 3 #%i", index + 1);
|
||||
dm->AddDevice(new DualShock3Device(index, temp, foundDevs[i].path));
|
||||
index++;
|
||||
}
|
||||
|
|
|
@ -45,35 +45,39 @@ typedef int64_t __int64;
|
|||
#include <cstdarg>
|
||||
|
||||
template <typename Array>
|
||||
void wsprintfW(Array& buf, const wchar_t *format, ...) {
|
||||
void wsprintfW(Array &buf, const wchar_t *format, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, format);
|
||||
|
||||
vswprintf(buf, sizeof(buf)/sizeof(buf[0]), format, a);
|
||||
vswprintf(buf, sizeof(buf) / sizeof(buf[0]), format, a);
|
||||
|
||||
va_end(a);
|
||||
}
|
||||
|
||||
template <typename Array>
|
||||
void wsprintf(Array& buf, const wchar_t *format, ...) {
|
||||
void wsprintf(Array &buf, const wchar_t *format, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, format);
|
||||
|
||||
vswprintf(buf, sizeof(buf)/sizeof(buf[0]), format, a);
|
||||
vswprintf(buf, sizeof(buf) / sizeof(buf[0]), format, a);
|
||||
|
||||
va_end(a);
|
||||
}
|
||||
|
||||
static inline int wcsicmp(const wchar_t* w1, const wchar_t* w2) {
|
||||
static inline int wcsicmp(const wchar_t *w1, const wchar_t *w2)
|
||||
{
|
||||
// I didn't find a way to put ignore case ...
|
||||
return wcscmp(w1, w2);
|
||||
}
|
||||
|
||||
#include <sys/time.h>
|
||||
static inline unsigned int timeGetTime() {
|
||||
static inline unsigned int timeGetTime()
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
uint64_t ms = (now.tv_usec/1000) + ((uint64_t)now.tv_sec * 1000);
|
||||
uint64_t ms = (now.tv_usec / 1000) + ((uint64_t)now.tv_sec * 1000);
|
||||
return (ms & 0xFFFFFFFF); // MS code is u32 ...
|
||||
}
|
||||
|
||||
|
@ -95,7 +99,7 @@ extern Window GSwin;
|
|||
#ifdef _MSC_VER
|
||||
#define EXPORT_C_(type) extern "C" type CALLBACK
|
||||
#else
|
||||
#define EXPORT_C_(type) extern "C" __attribute__((stdcall,externally_visible,visibility("default"))) type CALLBACK
|
||||
#define EXPORT_C_(type) extern "C" __attribute__((stdcall, externally_visible, visibility("default"))) type CALLBACK
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -136,7 +140,8 @@ extern HINSTANCE hInst;
|
|||
// Needed for config screen
|
||||
void GetNameAndVersionString(wchar_t *out);
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
unsigned char controllerType;
|
||||
unsigned short buttonStatus;
|
||||
unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY;
|
||||
|
@ -144,27 +149,51 @@ typedef struct {
|
|||
unsigned char reserved[91];
|
||||
} PadDataS;
|
||||
|
||||
EXPORT_C_(void) PADupdate(int pad);
|
||||
EXPORT_C_(u32) PS2EgetLibType(void);
|
||||
EXPORT_C_(u32) PS2EgetLibVersion2(u32 type);
|
||||
EXPORT_C_(char*) PSEgetLibName();
|
||||
EXPORT_C_(char*) PS2EgetLibName(void);
|
||||
EXPORT_C_(void) PADshutdown();
|
||||
EXPORT_C_(s32) PADinit(u32 flags);
|
||||
EXPORT_C_(s32) PADopen(void *pDsp);
|
||||
EXPORT_C_(void) PADclose();
|
||||
EXPORT_C_(u8) PADstartPoll(int pad);
|
||||
EXPORT_C_(u8) PADpoll(u8 value);
|
||||
EXPORT_C_(u32) PADquery();
|
||||
EXPORT_C_(void) PADabout();
|
||||
EXPORT_C_(s32) PADtest();
|
||||
EXPORT_C_(keyEvent*) PADkeyEvent();
|
||||
EXPORT_C_(u32) PADreadPort1 (PadDataS* pads);
|
||||
EXPORT_C_(u32) PADreadPort2 (PadDataS* pads);
|
||||
EXPORT_C_(u32) PSEgetLibType();
|
||||
EXPORT_C_(u32) PSEgetLibVersion();
|
||||
EXPORT_C_(void) PADconfigure();
|
||||
EXPORT_C_(s32) PADfreeze(int mode, freezeData *data);
|
||||
EXPORT_C_(s32) PADsetSlot(u8 port, u8 slot);
|
||||
EXPORT_C_(s32) PADqueryMtap(u8 port);
|
||||
EXPORT_C_(void) PADsetSettingsDir(const char *dir);
|
||||
EXPORT_C_(void)
|
||||
PADupdate(int pad);
|
||||
EXPORT_C_(u32)
|
||||
PS2EgetLibType(void);
|
||||
EXPORT_C_(u32)
|
||||
PS2EgetLibVersion2(u32 type);
|
||||
EXPORT_C_(char *)
|
||||
PSEgetLibName();
|
||||
EXPORT_C_(char *)
|
||||
PS2EgetLibName(void);
|
||||
EXPORT_C_(void)
|
||||
PADshutdown();
|
||||
EXPORT_C_(s32)
|
||||
PADinit(u32 flags);
|
||||
EXPORT_C_(s32)
|
||||
PADopen(void *pDsp);
|
||||
EXPORT_C_(void)
|
||||
PADclose();
|
||||
EXPORT_C_(u8)
|
||||
PADstartPoll(int pad);
|
||||
EXPORT_C_(u8)
|
||||
PADpoll(u8 value);
|
||||
EXPORT_C_(u32)
|
||||
PADquery();
|
||||
EXPORT_C_(void)
|
||||
PADabout();
|
||||
EXPORT_C_(s32)
|
||||
PADtest();
|
||||
EXPORT_C_(keyEvent *)
|
||||
PADkeyEvent();
|
||||
EXPORT_C_(u32)
|
||||
PADreadPort1(PadDataS *pads);
|
||||
EXPORT_C_(u32)
|
||||
PADreadPort2(PadDataS *pads);
|
||||
EXPORT_C_(u32)
|
||||
PSEgetLibType();
|
||||
EXPORT_C_(u32)
|
||||
PSEgetLibVersion();
|
||||
EXPORT_C_(void)
|
||||
PADconfigure();
|
||||
EXPORT_C_(s32)
|
||||
PADfreeze(int mode, freezeData *data);
|
||||
EXPORT_C_(s32)
|
||||
PADsetSlot(u8 port, u8 slot);
|
||||
EXPORT_C_(s32)
|
||||
PADqueryMtap(u8 port);
|
||||
EXPORT_C_(void)
|
||||
PADsetSettingsDir(const char *dir);
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
#include <setupapi.h>
|
||||
#include <hidsdi.h>
|
||||
|
||||
int FindHids(HidDeviceInfo **foundDevs, int vid, int pid) {
|
||||
int FindHids(HidDeviceInfo **foundDevs, int vid, int pid)
|
||||
{
|
||||
GUID GUID_DEVINTERFACE_HID;
|
||||
int numFoundDevs = 0;
|
||||
*foundDevs = 0;
|
||||
|
@ -29,19 +30,22 @@ int FindHids(HidDeviceInfo **foundDevs, int vid, int pid) {
|
|||
if (hdev != INVALID_HANDLE_VALUE) {
|
||||
SP_DEVICE_INTERFACE_DATA devInterfaceData;
|
||||
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
for (int i=0; SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVINTERFACE_HID, i, &devInterfaceData); i++) {
|
||||
for (int i = 0; SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVINTERFACE_HID, i, &devInterfaceData); i++) {
|
||||
|
||||
DWORD size = 0;
|
||||
SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, 0, 0, &size, 0);
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !size) continue;
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA *) malloc(size);
|
||||
if (!devInterfaceDetails) continue;
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !size)
|
||||
continue;
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(size);
|
||||
if (!devInterfaceDetails)
|
||||
continue;
|
||||
|
||||
devInterfaceDetails->cbSize = sizeof(*devInterfaceDetails);
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
if (!SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, devInterfaceDetails, size, &size, &devInfoData)) continue;
|
||||
if (!SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, devInterfaceDetails, size, &size, &devInfoData))
|
||||
continue;
|
||||
|
||||
HANDLE hfile = CreateFile(devInterfaceDetails->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
@ -54,7 +58,7 @@ int FindHids(HidDeviceInfo **foundDevs, int vid, int pid) {
|
|||
if (HidD_GetPreparsedData(hfile, &pData)) {
|
||||
if (HidP_GetCaps(pData, &caps) == HIDP_STATUS_SUCCESS) {
|
||||
if (numFoundDevs % 32 == 0) {
|
||||
*foundDevs = (HidDeviceInfo*) realloc(*foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs));
|
||||
*foundDevs = (HidDeviceInfo *)realloc(*foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs));
|
||||
}
|
||||
HidDeviceInfo *dev = &foundDevs[0][numFoundDevs++];
|
||||
dev->caps = caps;
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
|
||||
#include <hidsdi.h>
|
||||
|
||||
struct HidDeviceInfo {
|
||||
struct HidDeviceInfo
|
||||
{
|
||||
HIDP_CAPS caps;
|
||||
wchar_t *path;
|
||||
unsigned short vid;
|
||||
|
|
|
@ -21,12 +21,14 @@
|
|||
|
||||
InputDeviceManager *dm = 0;
|
||||
|
||||
InputDeviceManager::InputDeviceManager() {
|
||||
InputDeviceManager::InputDeviceManager()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
void InputDeviceManager::ClearDevices() {
|
||||
for (int i=0; i<numDevices; i++) {
|
||||
void InputDeviceManager::ClearDevices()
|
||||
{
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
delete devices[i];
|
||||
}
|
||||
free(devices);
|
||||
|
@ -34,11 +36,13 @@ void InputDeviceManager::ClearDevices() {
|
|||
numDevices = 0;
|
||||
}
|
||||
|
||||
InputDeviceManager::~InputDeviceManager() {
|
||||
InputDeviceManager::~InputDeviceManager()
|
||||
{
|
||||
ClearDevices();
|
||||
}
|
||||
|
||||
Device::Device(DeviceAPI api, DeviceType d, const wchar_t *displayName, const wchar_t *instanceID, const wchar_t *productID) {
|
||||
Device::Device(DeviceAPI api, DeviceType d, const wchar_t *displayName, const wchar_t *instanceID, const wchar_t *productID)
|
||||
{
|
||||
memset(pads, 0, sizeof(pads));
|
||||
this->api = api;
|
||||
type = d;
|
||||
|
@ -73,22 +77,25 @@ Device::Device(DeviceAPI api, DeviceType d, const wchar_t *displayName, const wc
|
|||
numFFAxes = 0;
|
||||
}
|
||||
|
||||
void Device::FreeState() {
|
||||
if (virtualControlState) free(virtualControlState);
|
||||
void Device::FreeState()
|
||||
{
|
||||
if (virtualControlState)
|
||||
free(virtualControlState);
|
||||
virtualControlState = 0;
|
||||
oldVirtualControlState = 0;
|
||||
physicalControlState = 0;
|
||||
}
|
||||
|
||||
Device::~Device() {
|
||||
Device::~Device()
|
||||
{
|
||||
Deactivate();
|
||||
// Generally called by deactivate, but just in case...
|
||||
FreeState();
|
||||
int i;
|
||||
for (int port=0; port<2; port++) {
|
||||
for (int slot=0; slot<4; slot++) {
|
||||
for (int port = 0; port < 2; port++) {
|
||||
for (int slot = 0; slot < 4; slot++) {
|
||||
free(pads[port][slot].bindings);
|
||||
for (i=0; i<pads[port][slot].numFFBindings; i++) {
|
||||
for (i = 0; i < pads[port][slot].numFFBindings; i++) {
|
||||
free(pads[port][slot].ffBindings[i].axes);
|
||||
}
|
||||
free(pads[port][slot].ffBindings);
|
||||
|
@ -96,8 +103,9 @@ Device::~Device() {
|
|||
}
|
||||
free(virtualControls);
|
||||
|
||||
for (i=numPhysicalControls-1; i>=0; i--) {
|
||||
if (physicalControls[i].name) free(physicalControls[i].name);
|
||||
for (i = numPhysicalControls - 1; i >= 0; i--) {
|
||||
if (physicalControls[i].name)
|
||||
free(physicalControls[i].name);
|
||||
}
|
||||
free(physicalControls);
|
||||
|
||||
|
@ -105,13 +113,13 @@ Device::~Device() {
|
|||
free(instanceID);
|
||||
free(productID);
|
||||
if (ffAxes) {
|
||||
for (i=0; i<numFFAxes; i++) {
|
||||
for (i = 0; i < numFFAxes; i++) {
|
||||
free(ffAxes[i].displayName);
|
||||
}
|
||||
free(ffAxes);
|
||||
}
|
||||
if (ffEffectTypes) {
|
||||
for (i=0; i<numFFEffectTypes; i++) {
|
||||
for (i = 0; i < numFFEffectTypes; i++) {
|
||||
free(ffEffectTypes[i].displayName);
|
||||
free(ffEffectTypes[i].effectID);
|
||||
}
|
||||
|
@ -119,71 +127,77 @@ Device::~Device() {
|
|||
}
|
||||
}
|
||||
|
||||
void Device::AddFFEffectType(const wchar_t *displayName, const wchar_t *effectID, EffectType type) {
|
||||
ffEffectTypes = (ForceFeedbackEffectType*) realloc(ffEffectTypes, sizeof(ForceFeedbackEffectType) * (numFFEffectTypes+1));
|
||||
void Device::AddFFEffectType(const wchar_t *displayName, const wchar_t *effectID, EffectType type)
|
||||
{
|
||||
ffEffectTypes = (ForceFeedbackEffectType *)realloc(ffEffectTypes, sizeof(ForceFeedbackEffectType) * (numFFEffectTypes + 1));
|
||||
ffEffectTypes[numFFEffectTypes].displayName = wcsdup(displayName);
|
||||
ffEffectTypes[numFFEffectTypes].effectID = wcsdup(effectID);
|
||||
ffEffectTypes[numFFEffectTypes].type = type;
|
||||
numFFEffectTypes++;
|
||||
}
|
||||
|
||||
void Device::AddFFAxis(const wchar_t *displayName, int id) {
|
||||
ffAxes = (ForceFeedbackAxis*) realloc(ffAxes, sizeof(ForceFeedbackAxis) * (numFFAxes+1));
|
||||
void Device::AddFFAxis(const wchar_t *displayName, int id)
|
||||
{
|
||||
ffAxes = (ForceFeedbackAxis *)realloc(ffAxes, sizeof(ForceFeedbackAxis) * (numFFAxes + 1));
|
||||
ffAxes[numFFAxes].id = id;
|
||||
ffAxes[numFFAxes].displayName = wcsdup(displayName);
|
||||
numFFAxes++;
|
||||
int bindingsExist = 0;
|
||||
for (int port=0; port<2; port++) {
|
||||
for (int slot=0; slot<4; slot++) {
|
||||
for (int i=0; i<pads[port][slot].numFFBindings; i++) {
|
||||
ForceFeedbackBinding *b = pads[port][slot].ffBindings+i;
|
||||
b->axes = (AxisEffectInfo*) realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes));
|
||||
memset(b->axes + (numFFAxes-1), 0, sizeof(AxisEffectInfo));
|
||||
for (int port = 0; port < 2; port++) {
|
||||
for (int slot = 0; slot < 4; slot++) {
|
||||
for (int i = 0; i < pads[port][slot].numFFBindings; i++) {
|
||||
ForceFeedbackBinding *b = pads[port][slot].ffBindings + i;
|
||||
b->axes = (AxisEffectInfo *)realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes));
|
||||
memset(b->axes + (numFFAxes - 1), 0, sizeof(AxisEffectInfo));
|
||||
bindingsExist = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Generally the case when not loading a binding file.
|
||||
if (!bindingsExist) {
|
||||
int i = numFFAxes-1;
|
||||
int i = numFFAxes - 1;
|
||||
ForceFeedbackAxis temp = ffAxes[i];
|
||||
while (i && temp.id < ffAxes[i-1].id) {
|
||||
ffAxes[i] = ffAxes[i-1];
|
||||
while (i && temp.id < ffAxes[i - 1].id) {
|
||||
ffAxes[i] = ffAxes[i - 1];
|
||||
i--;
|
||||
}
|
||||
ffAxes[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void Device::AllocState() {
|
||||
void Device::AllocState()
|
||||
{
|
||||
FreeState();
|
||||
virtualControlState = (int*) calloc(numVirtualControls + numVirtualControls + numPhysicalControls, sizeof(int));
|
||||
virtualControlState = (int *)calloc(numVirtualControls + numVirtualControls + numPhysicalControls, sizeof(int));
|
||||
oldVirtualControlState = virtualControlState + numVirtualControls;
|
||||
physicalControlState = oldVirtualControlState + numVirtualControls;
|
||||
}
|
||||
|
||||
void Device::FlipState() {
|
||||
memcpy(oldVirtualControlState, virtualControlState, sizeof(int)*numVirtualControls);
|
||||
void Device::FlipState()
|
||||
{
|
||||
memcpy(oldVirtualControlState, virtualControlState, sizeof(int) * numVirtualControls);
|
||||
}
|
||||
|
||||
void Device::PostRead() {
|
||||
void Device::PostRead()
|
||||
{
|
||||
FlipState();
|
||||
}
|
||||
|
||||
void Device::CalcVirtualState() {
|
||||
for (int i=0; i<numPhysicalControls; i++) {
|
||||
PhysicalControl *c = physicalControls+i;
|
||||
void Device::CalcVirtualState()
|
||||
{
|
||||
for (int i = 0; i < numPhysicalControls; i++) {
|
||||
PhysicalControl *c = physicalControls + i;
|
||||
int index = c->baseVirtualControlIndex;
|
||||
int val = physicalControlState[i];
|
||||
if (c->type & BUTTON) {
|
||||
virtualControlState[index] = val;
|
||||
// DirectInput keyboard events only.
|
||||
if (this->api == DI && this->type == KEYBOARD) {
|
||||
if (!(virtualControlState[index]>>15) != !(oldVirtualControlState[index]>>15) && c->vkey) {
|
||||
if (!(virtualControlState[index] >> 15) != !(oldVirtualControlState[index] >> 15) && c->vkey) {
|
||||
// Check for alt-F4 to avoid toggling skip mode incorrectly.
|
||||
if (c->vkey == VK_F4) {
|
||||
int i;
|
||||
for (i=0; i<numPhysicalControls; i++) {
|
||||
for (i = 0; i < numPhysicalControls; i++) {
|
||||
if (virtualControlState[physicalControls[i].baseVirtualControlIndex] &&
|
||||
(physicalControls[i].vkey == VK_MENU ||
|
||||
physicalControls[i].vkey == VK_RMENU ||
|
||||
|
@ -191,72 +205,73 @@ void Device::CalcVirtualState() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (i<numPhysicalControls) continue;
|
||||
if (i < numPhysicalControls)
|
||||
continue;
|
||||
}
|
||||
int event = KEYPRESS;
|
||||
if (!(virtualControlState[index]>>15)) event = KEYRELEASE;
|
||||
if (!(virtualControlState[index] >> 15))
|
||||
event = KEYRELEASE;
|
||||
QueueKeyEvent(c->vkey, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (c->type & ABSAXIS) {
|
||||
virtualControlState[index] = (val + FULLY_DOWN)/2;
|
||||
} else if (c->type & ABSAXIS) {
|
||||
virtualControlState[index] = (val + FULLY_DOWN) / 2;
|
||||
// Positive. Overkill.
|
||||
virtualControlState[index+1] = (val & ~(val>>31));
|
||||
virtualControlState[index + 1] = (val & ~(val >> 31));
|
||||
// Negative
|
||||
virtualControlState[index+2] = (-val & (val>>31));
|
||||
}
|
||||
else if (c->type & RELAXIS) {
|
||||
virtualControlState[index + 2] = (-val & (val >> 31));
|
||||
} else if (c->type & RELAXIS) {
|
||||
int delta = val - oldVirtualControlState[index];
|
||||
virtualControlState[index] = val;
|
||||
// Positive
|
||||
virtualControlState[index+1] = (delta & ~(delta>>31));
|
||||
virtualControlState[index + 1] = (delta & ~(delta >> 31));
|
||||
// Negative
|
||||
virtualControlState[index+2] = (-delta & (delta>>31));
|
||||
}
|
||||
else if (c->type & POV) {
|
||||
virtualControlState[index + 2] = (-delta & (delta >> 31));
|
||||
} else if (c->type & POV) {
|
||||
virtualControlState[index] = val;
|
||||
int iSouth = 0;
|
||||
int iEast = 0;
|
||||
if ((unsigned int)val <= 37000) {
|
||||
double angle = val * (3.141592653589793/18000.0);
|
||||
double angle = val * (3.141592653589793 / 18000.0);
|
||||
double East = sin(angle);
|
||||
double South = -cos(angle);
|
||||
// Normalize so greatest direction is 1.
|
||||
// Normalize so greatest direction is 1.
|
||||
#ifdef __linux__
|
||||
double mul = FULLY_DOWN / std::max(fabs(South), fabs(East));
|
||||
#else
|
||||
double mul = FULLY_DOWN / max(fabs(South), fabs(East));
|
||||
#endif
|
||||
iEast = (int) floor(East * mul + 0.5);
|
||||
iSouth = (int) floor(South * mul + 0.5);
|
||||
iEast = (int)floor(East * mul + 0.5);
|
||||
iSouth = (int)floor(South * mul + 0.5);
|
||||
}
|
||||
// N
|
||||
virtualControlState[index+1] = (-iSouth & (iSouth>>31));
|
||||
virtualControlState[index + 1] = (-iSouth & (iSouth >> 31));
|
||||
// S
|
||||
virtualControlState[index+3] = (iSouth & ~(iSouth>>31));
|
||||
virtualControlState[index + 3] = (iSouth & ~(iSouth >> 31));
|
||||
// E
|
||||
virtualControlState[index+2] = (iEast & ~(iEast>>31));
|
||||
virtualControlState[index + 2] = (iEast & ~(iEast >> 31));
|
||||
// W
|
||||
virtualControlState[index+4] = (-iEast & (iEast>>31));
|
||||
virtualControlState[index + 4] = (-iEast & (iEast >> 31));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VirtualControl *Device::GetVirtualControl(unsigned int uid) {
|
||||
for (int i=0; i<numVirtualControls; i++) {
|
||||
VirtualControl *Device::GetVirtualControl(unsigned int uid)
|
||||
{
|
||||
for (int i = 0; i < numVirtualControls; i++) {
|
||||
if (virtualControls[i].uid == uid)
|
||||
return virtualControls + i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
VirtualControl *Device::AddVirtualControl(unsigned int uid, int physicalControlIndex) {
|
||||
VirtualControl *Device::AddVirtualControl(unsigned int uid, int physicalControlIndex)
|
||||
{
|
||||
// Not really necessary, as always call AllocState when activated, but doesn't hurt.
|
||||
FreeState();
|
||||
|
||||
if (numVirtualControls % 16 == 0) {
|
||||
virtualControls = (VirtualControl*) realloc(virtualControls, sizeof(VirtualControl)*(numVirtualControls+16));
|
||||
virtualControls = (VirtualControl *)realloc(virtualControls, sizeof(VirtualControl) * (numVirtualControls + 16));
|
||||
}
|
||||
VirtualControl *c = virtualControls + numVirtualControls;
|
||||
|
||||
|
@ -267,31 +282,31 @@ VirtualControl *Device::AddVirtualControl(unsigned int uid, int physicalControlI
|
|||
return c;
|
||||
}
|
||||
|
||||
PhysicalControl *Device::AddPhysicalControl(ControlType type, unsigned short id, unsigned short vkey, const wchar_t *name) {
|
||||
PhysicalControl *Device::AddPhysicalControl(ControlType type, unsigned short id, unsigned short vkey, const wchar_t *name)
|
||||
{
|
||||
// Not really necessary, as always call AllocState when activated, but doesn't hurt.
|
||||
FreeState();
|
||||
|
||||
if (numPhysicalControls % 16 == 0) {
|
||||
physicalControls = (PhysicalControl*) realloc(physicalControls, sizeof(PhysicalControl)*(numPhysicalControls+16));
|
||||
physicalControls = (PhysicalControl *)realloc(physicalControls, sizeof(PhysicalControl) * (numPhysicalControls + 16));
|
||||
}
|
||||
PhysicalControl *control = physicalControls + numPhysicalControls;
|
||||
|
||||
memset(control, 0, sizeof(PhysicalControl));
|
||||
control->type = type;
|
||||
control->id = id;
|
||||
if (name) control->name = wcsdup(name);
|
||||
if (name)
|
||||
control->name = wcsdup(name);
|
||||
control->baseVirtualControlIndex = numVirtualControls;
|
||||
unsigned int uid = id | (type<<16);
|
||||
unsigned int uid = id | (type << 16);
|
||||
if (type & BUTTON) {
|
||||
AddVirtualControl(uid, numPhysicalControls);
|
||||
control->vkey = vkey;
|
||||
}
|
||||
else if (type & AXIS) {
|
||||
} else if (type & AXIS) {
|
||||
AddVirtualControl(uid | UID_AXIS, numPhysicalControls);
|
||||
AddVirtualControl(uid | UID_AXIS_POS, numPhysicalControls);
|
||||
AddVirtualControl(uid | UID_AXIS_NEG, numPhysicalControls);
|
||||
}
|
||||
else if (type & POV) {
|
||||
} else if (type & POV) {
|
||||
AddVirtualControl(uid | UID_POV, numPhysicalControls);
|
||||
AddVirtualControl(uid | UID_POV_N, numPhysicalControls);
|
||||
AddVirtualControl(uid | UID_POV_E, numPhysicalControls);
|
||||
|
@ -302,88 +317,91 @@ PhysicalControl *Device::AddPhysicalControl(ControlType type, unsigned short id,
|
|||
return control;
|
||||
}
|
||||
|
||||
void Device::SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) {
|
||||
for (int i=0; i<pads[port][slot].numFFBindings; i++) {
|
||||
ForceFeedbackBinding *binding = pads[port][slot].ffBindings+i;
|
||||
void Device::SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force)
|
||||
{
|
||||
for (int i = 0; i < pads[port][slot].numFFBindings; i++) {
|
||||
ForceFeedbackBinding *binding = pads[port][slot].ffBindings + i;
|
||||
if (binding->motor == motor) {
|
||||
SetEffect(binding, force);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t *GetDefaultControlName(unsigned short id, int type) {
|
||||
wchar_t *GetDefaultControlName(unsigned short id, int type)
|
||||
{
|
||||
static wchar_t name[20];
|
||||
if (type & BUTTON) {
|
||||
wsprintfW(name, L"Button %i", id);
|
||||
}
|
||||
else if (type & AXIS) {
|
||||
} else if (type & AXIS) {
|
||||
wsprintfW(name, L"Axis %i", id);
|
||||
}
|
||||
else if (type & POV) {
|
||||
} else if (type & POV) {
|
||||
wsprintfW(name, L"POV %i", id);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
wcscpy(name, L"Unknown");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
wchar_t *Device::GetVirtualControlName(VirtualControl *control) {
|
||||
wchar_t *Device::GetVirtualControlName(VirtualControl *control)
|
||||
{
|
||||
static wchar_t temp[100];
|
||||
wchar_t *baseName = 0;
|
||||
if (control->physicalControlIndex >= 0) {
|
||||
baseName = physicalControls[control->physicalControlIndex].name;
|
||||
if (!baseName) baseName = GetPhysicalControlName(&physicalControls[control->physicalControlIndex]);
|
||||
if (!baseName)
|
||||
baseName = GetPhysicalControlName(&physicalControls[control->physicalControlIndex]);
|
||||
}
|
||||
unsigned int uid = control->uid;
|
||||
if (!baseName) {
|
||||
baseName = GetDefaultControlName(uid & 0xFFFF, (uid >> 16)& 0x1F);
|
||||
baseName = GetDefaultControlName(uid & 0xFFFF, (uid >> 16) & 0x1F);
|
||||
}
|
||||
uid &= 0xFF000000;
|
||||
int len = (int)wcslen(baseName);
|
||||
if (len > 99) len = 99;
|
||||
memcpy(temp, baseName, len*sizeof(wchar_t));
|
||||
if (len > 99)
|
||||
len = 99;
|
||||
memcpy(temp, baseName, len * sizeof(wchar_t));
|
||||
temp[len] = 0;
|
||||
if (uid) {
|
||||
if (len > 95) len = 95;
|
||||
wchar_t *out = temp+len;
|
||||
if (len > 95)
|
||||
len = 95;
|
||||
wchar_t *out = temp + len;
|
||||
if (uid == UID_AXIS_POS) {
|
||||
wcscpy(out, L" +");
|
||||
}
|
||||
else if (uid == UID_AXIS_NEG) {
|
||||
} else if (uid == UID_AXIS_NEG) {
|
||||
wcscpy(out, L" -");
|
||||
}
|
||||
else if (uid == UID_POV_N) {
|
||||
} else if (uid == UID_POV_N) {
|
||||
wcscpy(out, L" N");
|
||||
}
|
||||
else if (uid == UID_POV_E) {
|
||||
} else if (uid == UID_POV_E) {
|
||||
wcscpy(out, L" E");
|
||||
}
|
||||
else if (uid == UID_POV_S) {
|
||||
} else if (uid == UID_POV_S) {
|
||||
wcscpy(out, L" S");
|
||||
}
|
||||
else if (uid == UID_POV_W) {
|
||||
} else if (uid == UID_POV_W) {
|
||||
wcscpy(out, L" W");
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
wchar_t *Device::GetPhysicalControlName(PhysicalControl *control) {
|
||||
if (control->name) return control->name;
|
||||
wchar_t *Device::GetPhysicalControlName(PhysicalControl *control)
|
||||
{
|
||||
if (control->name)
|
||||
return control->name;
|
||||
return GetDefaultControlName(control->id, control->type);
|
||||
}
|
||||
|
||||
void InputDeviceManager::AddDevice(Device *d) {
|
||||
devices = (Device**) realloc(devices, sizeof(Device*) * (numDevices+1));
|
||||
void InputDeviceManager::AddDevice(Device *d)
|
||||
{
|
||||
devices = (Device **)realloc(devices, sizeof(Device *) * (numDevices + 1));
|
||||
devices[numDevices++] = d;
|
||||
}
|
||||
|
||||
void InputDeviceManager::Update(InitInfo *info) {
|
||||
for (int i=0; i<numDevices; i++) {
|
||||
void InputDeviceManager::Update(InitInfo *info)
|
||||
{
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
if (devices[i]->enabled) {
|
||||
if (!devices[i]->active) {
|
||||
if (!devices[i]->Activate(info) || !devices[i]->Update()) continue;
|
||||
if (!devices[i]->Activate(info) || !devices[i]->Update())
|
||||
continue;
|
||||
devices[i]->CalcVirtualState();
|
||||
devices[i]->PostRead();
|
||||
}
|
||||
|
@ -393,49 +411,53 @@ void InputDeviceManager::Update(InitInfo *info) {
|
|||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::PostRead() {
|
||||
for (int i=0; i<numDevices; i++) {
|
||||
void InputDeviceManager::PostRead()
|
||||
{
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
if (devices[i]->active)
|
||||
devices[i]->PostRead();
|
||||
}
|
||||
}
|
||||
|
||||
Device *InputDeviceManager::GetActiveDevice(InitInfo *info, unsigned int *uid, int *index, int *value) {
|
||||
Device *InputDeviceManager::GetActiveDevice(InitInfo *info, unsigned int *uid, int *index, int *value)
|
||||
{
|
||||
int i, j;
|
||||
Update(info);
|
||||
int bestDiff = FULLY_DOWN/2;
|
||||
int bestDiff = FULLY_DOWN / 2;
|
||||
Device *bestDevice = 0;
|
||||
for (i=0; i<numDevices; i++) {
|
||||
for (i = 0; i < numDevices; i++) {
|
||||
if (devices[i]->active) {
|
||||
for (j=0; j<devices[i]->numVirtualControls; j++) {
|
||||
if (devices[i]->virtualControlState[j] == devices[i]->oldVirtualControlState[j]) continue;
|
||||
if (devices[i]->virtualControls[j].uid & UID_POV) continue;
|
||||
for (j = 0; j < devices[i]->numVirtualControls; j++) {
|
||||
if (devices[i]->virtualControlState[j] == devices[i]->oldVirtualControlState[j])
|
||||
continue;
|
||||
if (devices[i]->virtualControls[j].uid & UID_POV)
|
||||
continue;
|
||||
// Fix for releasing button used to click on bind button
|
||||
if (!((devices[i]->virtualControls[j].uid>>16) & (POV|RELAXIS|ABSAXIS))) {
|
||||
if (!((devices[i]->virtualControls[j].uid >> 16) & (POV | RELAXIS | ABSAXIS))) {
|
||||
if (abs(devices[i]->oldVirtualControlState[j]) > abs(devices[i]->virtualControlState[j])) {
|
||||
devices[i]->oldVirtualControlState[j] = 0;
|
||||
}
|
||||
}
|
||||
int diff = abs(devices[i]->virtualControlState[j] - devices[i]->oldVirtualControlState[j]);
|
||||
// Make it require a bit more work to bind relative axes.
|
||||
if (((devices[i]->virtualControls[j].uid>>16) & 0xFF) == RELAXIS) {
|
||||
diff = diff/4+1;
|
||||
if (((devices[i]->virtualControls[j].uid >> 16) & 0xFF) == RELAXIS) {
|
||||
diff = diff / 4 + 1;
|
||||
}
|
||||
// Less pressure needed to bind DS3/SCP buttons.
|
||||
if ((devices[i]->api == DS3 || devices[i]->api == XINPUT) && (((devices[i]->virtualControls[j].uid>>16) & 0xFF) & BUTTON)) {
|
||||
if ((devices[i]->api == DS3 || devices[i]->api == XINPUT) && (((devices[i]->virtualControls[j].uid >> 16) & 0xFF) & BUTTON)) {
|
||||
diff *= 4;
|
||||
}
|
||||
if (diff > bestDiff) {
|
||||
if (devices[i]->virtualControls[j].uid & UID_AXIS) {
|
||||
if ((((devices[i]->virtualControls[j].uid>>16)&0xFF) != ABSAXIS)) continue;
|
||||
if ((((devices[i]->virtualControls[j].uid >> 16) & 0xFF) != ABSAXIS))
|
||||
continue;
|
||||
// Very picky when binding entire axes. Prefer binding half-axes.
|
||||
if (!((devices[i]->oldVirtualControlState[j] < FULLY_DOWN/32 && devices[i]->virtualControlState[j] > FULLY_DOWN/8) ||
|
||||
(devices[i]->oldVirtualControlState[j] > 31*FULLY_DOWN/32 && devices[i]->virtualControlState[j] < 7*FULLY_DOWN/8))) {
|
||||
if (!((devices[i]->oldVirtualControlState[j] < FULLY_DOWN / 32 && devices[i]->virtualControlState[j] > FULLY_DOWN / 8) ||
|
||||
(devices[i]->oldVirtualControlState[j] > 31 * FULLY_DOWN / 32 && devices[i]->virtualControlState[j] < 7 * FULLY_DOWN / 8))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ((((devices[i]->virtualControls[j].uid>>16)&0xFF) == ABSAXIS)) {
|
||||
if (devices[i]->oldVirtualControlState[j] > 15*FULLY_DOWN/16)
|
||||
} else if ((((devices[i]->virtualControls[j].uid >> 16) & 0xFF) == ABSAXIS)) {
|
||||
if (devices[i]->oldVirtualControlState[j] > 15 * FULLY_DOWN / 16)
|
||||
continue;
|
||||
}
|
||||
bestDiff = diff;
|
||||
|
@ -443,10 +465,9 @@ Device *InputDeviceManager::GetActiveDevice(InitInfo *info, unsigned int *uid, i
|
|||
*index = j;
|
||||
bestDevice = devices[i];
|
||||
if (value) {
|
||||
if ((devices[i]->virtualControls[j].uid>>16)& RELAXIS) {
|
||||
if ((devices[i]->virtualControls[j].uid >> 16) & RELAXIS) {
|
||||
*value = devices[i]->virtualControlState[j] - devices[i]->oldVirtualControlState[j];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
*value = devices[i]->virtualControlState[j];
|
||||
}
|
||||
}
|
||||
|
@ -459,35 +480,41 @@ Device *InputDeviceManager::GetActiveDevice(InitInfo *info, unsigned int *uid, i
|
|||
return bestDevice;
|
||||
}
|
||||
|
||||
void InputDeviceManager::ReleaseInput() {
|
||||
for (int i=0; i<numDevices; i++) {
|
||||
if (devices[i]->active) devices[i]->Deactivate();
|
||||
void InputDeviceManager::ReleaseInput()
|
||||
{
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
if (devices[i]->active)
|
||||
devices[i]->Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::EnableDevices(DeviceType type, DeviceAPI api) {
|
||||
for (int i=0; i<numDevices; i++) {
|
||||
void InputDeviceManager::EnableDevices(DeviceType type, DeviceAPI api)
|
||||
{
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
if (devices[i]->api == api && devices[i]->type == type) {
|
||||
EnableDevice(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::DisableAllDevices() {
|
||||
for (int i=0; i<numDevices; i++) {
|
||||
void InputDeviceManager::DisableAllDevices()
|
||||
{
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
DisableDevice(i);
|
||||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::DisableDevice(int index) {
|
||||
void InputDeviceManager::DisableDevice(int index)
|
||||
{
|
||||
devices[index]->enabled = 0;
|
||||
if (devices[index]->active) {
|
||||
devices[index]->Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
ForceFeedbackEffectType *Device::GetForcefeedbackEffect(wchar_t *id) {
|
||||
for (int i=0; i<numFFEffectTypes; i++) {
|
||||
ForceFeedbackEffectType *Device::GetForcefeedbackEffect(wchar_t *id)
|
||||
{
|
||||
for (int i = 0; i < numFFEffectTypes; i++) {
|
||||
if (!wcsicmp(id, ffEffectTypes[i].effectID)) {
|
||||
return &ffEffectTypes[i];
|
||||
}
|
||||
|
@ -495,26 +522,29 @@ ForceFeedbackEffectType *Device::GetForcefeedbackEffect(wchar_t *id) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
ForceFeedbackAxis *Device::GetForceFeedbackAxis(int id) {
|
||||
for (int i=0; i<numFFAxes; i++) {
|
||||
if (ffAxes[i].id == id) return &ffAxes[i];
|
||||
ForceFeedbackAxis *Device::GetForceFeedbackAxis(int id)
|
||||
{
|
||||
for (int i = 0; i < numFFAxes; i++) {
|
||||
if (ffAxes[i].id == id)
|
||||
return &ffAxes[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
|
||||
int *oldMatches = (int*) malloc(sizeof(int) * numOldDevices);
|
||||
int *matches = (int*) malloc(sizeof(int) * numDevices);
|
||||
void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices)
|
||||
{
|
||||
int *oldMatches = (int *)malloc(sizeof(int) * numOldDevices);
|
||||
int *matches = (int *)malloc(sizeof(int) * numDevices);
|
||||
int i, j, port, slot;
|
||||
Device *old, *dev;
|
||||
for (i=0; i<numDevices; i++) {
|
||||
for (i = 0; i < numDevices; i++) {
|
||||
matches[i] = -1;
|
||||
}
|
||||
for (i=0; i<numOldDevices; i++) {
|
||||
for (i = 0; i < numOldDevices; i++) {
|
||||
oldMatches[i] = -2;
|
||||
old = oldDevices[i];
|
||||
for (port=0; port<2; port++) {
|
||||
for (slot=0; slot<4; slot++) {
|
||||
for (port = 0; port < 2; port++) {
|
||||
for (slot = 0; slot < 4; slot++) {
|
||||
if (old->pads[port][slot].numBindings + old->pads[port][slot].numFFBindings) {
|
||||
// Means that there are bindings.
|
||||
oldMatches[i] = -1;
|
||||
|
@ -523,10 +553,11 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
|
|||
}
|
||||
}
|
||||
// Loops through ids looking for match, from most specific to most general.
|
||||
for (int id=0; id<3; id++) {
|
||||
for (i=0; i<numOldDevices; i++) {
|
||||
if (oldMatches[i] >= 0) continue;
|
||||
for (j=0; j<numDevices; j++) {
|
||||
for (int id = 0; id < 3; id++) {
|
||||
for (i = 0; i < numOldDevices; i++) {
|
||||
if (oldMatches[i] >= 0)
|
||||
continue;
|
||||
for (j = 0; j < numDevices; j++) {
|
||||
if (matches[j] >= 0) {
|
||||
continue;
|
||||
}
|
||||
|
@ -544,37 +575,37 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
|
|||
}
|
||||
}
|
||||
|
||||
for (i=0; i<numOldDevices; i++) {
|
||||
if (oldMatches[i] == -2) continue;
|
||||
for (i = 0; i < numOldDevices; i++) {
|
||||
if (oldMatches[i] == -2)
|
||||
continue;
|
||||
old = oldDevices[i];
|
||||
if (oldMatches[i] < 0) {
|
||||
dev = new Device(old->api, old->type, old->displayName, old->instanceID, old->productID);
|
||||
dev->attached = 0;
|
||||
AddDevice(dev);
|
||||
for (j=0; j<old->numVirtualControls; j++) {
|
||||
VirtualControl *c = old->virtualControls+j;
|
||||
for (j = 0; j < old->numVirtualControls; j++) {
|
||||
VirtualControl *c = old->virtualControls + j;
|
||||
dev->AddVirtualControl(c->uid, -1);
|
||||
}
|
||||
for (j=0; j<old->numFFEffectTypes; j++) {
|
||||
ForceFeedbackEffectType * effect = old->ffEffectTypes + j;
|
||||
for (j = 0; j < old->numFFEffectTypes; j++) {
|
||||
ForceFeedbackEffectType *effect = old->ffEffectTypes + j;
|
||||
dev->AddFFEffectType(effect->displayName, effect->effectID, effect->type);
|
||||
}
|
||||
for (j=0; j<old->numFFAxes; j++) {
|
||||
ForceFeedbackAxis * axis = old->ffAxes + j;
|
||||
for (j = 0; j < old->numFFAxes; j++) {
|
||||
ForceFeedbackAxis *axis = old->ffAxes + j;
|
||||
dev->AddFFAxis(axis->displayName, axis->id);
|
||||
}
|
||||
// Just steal the old bindings directly when there's no matching device.
|
||||
// Indices will be the same.
|
||||
memcpy(dev->pads, old->pads, sizeof(old->pads));
|
||||
memset(old->pads, 0, sizeof(old->pads));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
dev = devices[oldMatches[i]];
|
||||
for (port=0; port<2; port++) {
|
||||
for (slot=0; slot<4; slot++) {
|
||||
for (port = 0; port < 2; port++) {
|
||||
for (slot = 0; slot < 4; slot++) {
|
||||
if (old->pads[port][slot].numBindings) {
|
||||
dev->pads[port][slot].bindings = (Binding*) malloc(old->pads[port][slot].numBindings * sizeof(Binding));
|
||||
for (int j=0; j<old->pads[port][slot].numBindings; j++) {
|
||||
dev->pads[port][slot].bindings = (Binding *)malloc(old->pads[port][slot].numBindings * sizeof(Binding));
|
||||
for (int j = 0; j < old->pads[port][slot].numBindings; j++) {
|
||||
Binding *bo = old->pads[port][slot].bindings + j;
|
||||
Binding *bn = dev->pads[port][slot].bindings + dev->pads[port][slot].numBindings;
|
||||
VirtualControl *cn = dev->GetVirtualControl(old->virtualControls[bo->controlIndex].uid);
|
||||
|
@ -586,16 +617,16 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
|
|||
}
|
||||
}
|
||||
if (old->pads[port][slot].numFFBindings) {
|
||||
dev->pads[port][slot].ffBindings = (ForceFeedbackBinding*) malloc(old->pads[port][slot].numFFBindings * sizeof(ForceFeedbackBinding));
|
||||
for (int j=0; j<old->pads[port][slot].numFFBindings; j++) {
|
||||
dev->pads[port][slot].ffBindings = (ForceFeedbackBinding *)malloc(old->pads[port][slot].numFFBindings * sizeof(ForceFeedbackBinding));
|
||||
for (int j = 0; j < old->pads[port][slot].numFFBindings; j++) {
|
||||
ForceFeedbackBinding *bo = old->pads[port][slot].ffBindings + j;
|
||||
ForceFeedbackBinding *bn = dev->pads[port][slot].ffBindings + dev->pads[port][slot].numFFBindings;
|
||||
ForceFeedbackEffectType *en = dev->GetForcefeedbackEffect(old->ffEffectTypes[bo->effectIndex].effectID);
|
||||
if (en) {
|
||||
*bn = *bo;
|
||||
bn->effectIndex = en - dev->ffEffectTypes;
|
||||
bn->axes = (AxisEffectInfo*)calloc(dev->numFFAxes, sizeof(AxisEffectInfo));
|
||||
for (int k=0; k<old->numFFAxes; k++) {
|
||||
bn->axes = (AxisEffectInfo *)calloc(dev->numFFAxes, sizeof(AxisEffectInfo));
|
||||
for (int k = 0; k < old->numFFAxes; k++) {
|
||||
ForceFeedbackAxis *newAxis = dev->GetForceFeedbackAxis(old->ffAxes[k].id);
|
||||
if (newAxis) {
|
||||
bn->axes[newAxis - dev->ffAxes] = bo->axes[k];
|
||||
|
@ -613,12 +644,12 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
|
|||
free(matches);
|
||||
}
|
||||
|
||||
void InputDeviceManager::SetEffect(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) {
|
||||
for (int i=0; i<numDevices; i++) {
|
||||
void InputDeviceManager::SetEffect(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force)
|
||||
{
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
Device *dev = devices[i];
|
||||
if (dev->enabled && dev->numFFEffectTypes) {
|
||||
dev->SetEffects(port, slot, motor, force);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
// Fully down means that value corresponds to a button being fully down (255).
|
||||
// a value of 128 or more corresponds to that button being pressed, for binary
|
||||
// values.
|
||||
#define BASE_SENSITIVITY (1<<16)
|
||||
#define FULLY_DOWN (1<<16)
|
||||
#define BASE_SENSITIVITY (1 << 16)
|
||||
#define FULLY_DOWN (1 << 16)
|
||||
|
||||
#define DEFAULT_DEADZONE (BASE_SENSITIVITY * 201/1000)
|
||||
#define DEFAULT_DEADZONE (BASE_SENSITIVITY * 201 / 1000)
|
||||
|
||||
/* Idea is for this file and the associated cpp file to be Windows independent.
|
||||
* Still more effort than it's worth to port to Linux, however.
|
||||
|
@ -65,7 +65,8 @@ enum ControlType {
|
|||
#define BINARY_BUTTON (PSHBTN | TGLBTN)
|
||||
#define AXIS 3
|
||||
|
||||
struct Binding {
|
||||
struct Binding
|
||||
{
|
||||
int controlIndex;
|
||||
int command;
|
||||
int sensitivity;
|
||||
|
@ -73,22 +74,23 @@ struct Binding {
|
|||
unsigned char turbo;
|
||||
};
|
||||
|
||||
#define UID_AXIS (1U<<31)
|
||||
#define UID_POV (1<<30)
|
||||
#define UID_AXIS (1U << 31)
|
||||
#define UID_POV (1 << 30)
|
||||
|
||||
#define UID_AXIS_POS (1U<<24)
|
||||
#define UID_AXIS_NEG (2U<<24)
|
||||
#define UID_POV_N (3<<24)
|
||||
#define UID_POV_E (4<<24)
|
||||
#define UID_POV_S (5<<24)
|
||||
#define UID_POV_W (6<<24)
|
||||
#define UID_AXIS_POS (1U << 24)
|
||||
#define UID_AXIS_NEG (2U << 24)
|
||||
#define UID_POV_N (3 << 24)
|
||||
#define UID_POV_E (4 << 24)
|
||||
#define UID_POV_S (5 << 24)
|
||||
#define UID_POV_W (6 << 24)
|
||||
|
||||
// One of these exists for each bindable object.
|
||||
// Bindable objects consist of buttons, axis, pov controls,
|
||||
// and individual axis/pov directions. Not that pov controls
|
||||
// cannot actually be bound, but when trying to bind as an axis,
|
||||
// all directions are assigned individually.
|
||||
struct VirtualControl {
|
||||
struct VirtualControl
|
||||
{
|
||||
// Unique id for control, given device. Based on source control's id,
|
||||
// source control type, axis/pov flags if it's a pov/axis (Rather than
|
||||
// a button or a pov/axis control's individual button), and an index,
|
||||
|
@ -103,7 +105,8 @@ struct VirtualControl {
|
|||
// updates their state, standard function then populates
|
||||
// the VirtualControls and queues the keyboard messages, if
|
||||
// needed.
|
||||
struct PhysicalControl {
|
||||
struct PhysicalControl
|
||||
{
|
||||
// index of the first virtual control corresponding to this.
|
||||
// Buttons have 1 virtual control, axes 3, and povs 5, all
|
||||
// in a row.
|
||||
|
@ -152,11 +155,13 @@ enum EffectType {
|
|||
// Order matches ForceFeedbackAxis order. force of 0 means to
|
||||
// ignore that axis completely. Force of 1 or -1 means to initialize
|
||||
// the axis with minimum force (Possibly 0 force), if applicable.
|
||||
struct AxisEffectInfo {
|
||||
struct AxisEffectInfo
|
||||
{
|
||||
int force;
|
||||
};
|
||||
|
||||
struct ForceFeedbackBinding {
|
||||
struct ForceFeedbackBinding
|
||||
{
|
||||
AxisEffectInfo *axes;
|
||||
int effectIndex;
|
||||
unsigned char motor;
|
||||
|
@ -164,7 +169,8 @@ struct ForceFeedbackBinding {
|
|||
|
||||
// Bindings listed by effect, so I don't have to bother with
|
||||
// indexing effects.
|
||||
struct ForceFeedbackEffectType {
|
||||
struct ForceFeedbackEffectType
|
||||
{
|
||||
wchar_t *displayName;
|
||||
// Because I'm lazy, can only have ASCII characters and no spaces.
|
||||
wchar_t *effectID;
|
||||
|
@ -173,7 +179,8 @@ struct ForceFeedbackEffectType {
|
|||
};
|
||||
|
||||
|
||||
struct ForceFeedbackAxis {
|
||||
struct ForceFeedbackAxis
|
||||
{
|
||||
wchar_t *displayName;
|
||||
int id;
|
||||
};
|
||||
|
@ -184,7 +191,8 @@ struct ForceFeedbackAxis {
|
|||
// one set of generic devices. Then I enumerate all devices. Then I merge
|
||||
// them, moving settings from the generic devices to the enumerated ones.
|
||||
|
||||
struct PadBindings {
|
||||
struct PadBindings
|
||||
{
|
||||
Binding *bindings;
|
||||
int numBindings;
|
||||
ForceFeedbackBinding *ffBindings;
|
||||
|
@ -193,7 +201,8 @@ struct PadBindings {
|
|||
|
||||
class WndProcEater;
|
||||
|
||||
struct InitInfo {
|
||||
struct InitInfo
|
||||
{
|
||||
// 1 when binding key to ignore.
|
||||
int bindingIgnore;
|
||||
// 1 when binding.
|
||||
|
@ -205,7 +214,7 @@ struct InitInfo {
|
|||
// For config screen, need to eat button's message handling.
|
||||
//HWND hWndButton;
|
||||
|
||||
WndProcEater* hWndProc;
|
||||
WndProcEater *hWndProc;
|
||||
#else
|
||||
// Linux equivalent to HWND
|
||||
Display *GSdsp;
|
||||
|
@ -216,7 +225,8 @@ struct InitInfo {
|
|||
|
||||
// Mostly self-contained, but bindings are modified by config.cpp, to make
|
||||
// updating the ListView simpler.
|
||||
class Device {
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
DeviceAPI api;
|
||||
DeviceType type;
|
||||
|
@ -228,13 +238,15 @@ public:
|
|||
#ifdef _MSC_VER
|
||||
// Not all devices need to subclass the windproc, but most do so might as well
|
||||
// put it here... --air
|
||||
WndProcEater* hWndProc;
|
||||
WndProcEater *hWndProc;
|
||||
#endif
|
||||
|
||||
union {
|
||||
union
|
||||
{
|
||||
// Allows for one loop to compare all 3 in order.
|
||||
wchar_t *IDs[3];
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
// Same as DisplayName, when not given. Absolutely must be unique.
|
||||
// Used for loading/saving controls. If matches, all other strings
|
||||
// are ignored, so must be unique.
|
||||
|
@ -298,17 +310,20 @@ public:
|
|||
|
||||
void CalcVirtualState();
|
||||
|
||||
virtual int Activate(InitInfo *args) {
|
||||
virtual int Activate(InitInfo *args)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline virtual void Deactivate() {
|
||||
inline virtual void Deactivate()
|
||||
{
|
||||
FreeState();
|
||||
active = 0;
|
||||
}
|
||||
|
||||
// Default update proc. All that's needed for post-based APIs.
|
||||
inline virtual int Update() {
|
||||
inline virtual int Update()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
|
@ -328,7 +343,8 @@ public:
|
|||
virtual void PostRead();
|
||||
};
|
||||
|
||||
class InputDeviceManager {
|
||||
class InputDeviceManager
|
||||
{
|
||||
public:
|
||||
Device **devices;
|
||||
int numDevices;
|
||||
|
@ -362,7 +378,8 @@ public:
|
|||
void ReleaseInput();
|
||||
|
||||
void DisableDevice(int index);
|
||||
inline void EnableDevice(int i) {
|
||||
inline void EnableDevice(int i)
|
||||
{
|
||||
devices[i]->enabled = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@ static u8 lastQueuedEvent = 0;
|
|||
static u8 nextQueuedEvent = 0;
|
||||
static keyEvent queuedEvents[EVENT_QUEUE_LEN];
|
||||
|
||||
void QueueKeyEvent(int key, int event) {
|
||||
void QueueKeyEvent(int key, int event)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
if (!csInitialized) {
|
||||
csInitialized = 1;
|
||||
|
@ -70,8 +71,10 @@ void QueueKeyEvent(int key, int event) {
|
|||
#endif
|
||||
}
|
||||
|
||||
int GetQueuedKeyEvent(keyEvent *event) {
|
||||
if (lastQueuedEvent == nextQueuedEvent) return 0;
|
||||
int GetQueuedKeyEvent(keyEvent *event)
|
||||
{
|
||||
if (lastQueuedEvent == nextQueuedEvent)
|
||||
return 0;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
EnterCriticalSection(&cSection);
|
||||
|
@ -86,7 +89,8 @@ int GetQueuedKeyEvent(keyEvent *event) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void ClearKeyQueue() {
|
||||
void ClearKeyQueue()
|
||||
{
|
||||
lastQueuedEvent = nextQueuedEvent;
|
||||
#ifdef _MSC_VER
|
||||
if (csInitialized) {
|
||||
|
|
|
@ -26,7 +26,7 @@ int GetQueuedKeyEvent(keyEvent *event);
|
|||
void ClearKeyQueue();
|
||||
|
||||
#ifdef __linux__
|
||||
void R_QueueKeyEvent(const keyEvent& event);
|
||||
void R_QueueKeyEvent(const keyEvent &event);
|
||||
int R_GetQueuedKeyEvent(keyEvent *event);
|
||||
void R_ClearKeyQueue();
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -73,61 +73,66 @@ remove 0x10F0 to compute the cmd value
|
|||
|
||||
#endif
|
||||
|
||||
struct GeneralSettingsBool {
|
||||
struct GeneralSettingsBool
|
||||
{
|
||||
const wchar_t *name;
|
||||
unsigned int ControlId;
|
||||
u8 defaultValue;
|
||||
};
|
||||
|
||||
// XXX: I try to remove only gui stuff
|
||||
void DeleteBinding(int port, int slot, Device *dev, Binding *b) {
|
||||
void DeleteBinding(int port, int slot, Device *dev, Binding *b)
|
||||
{
|
||||
fprintf(stderr, "delete binding %d:%d\n", port, slot);
|
||||
Binding *bindings = dev->pads[port][slot].bindings;
|
||||
int i = b - bindings;
|
||||
memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[port][slot].numBindings - i - 1));
|
||||
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot].numBindings - i - 1));
|
||||
dev->pads[port][slot].numBindings--;
|
||||
}
|
||||
|
||||
void DeleteBinding(int port, int slot, Device *dev, ForceFeedbackBinding *b) {
|
||||
void DeleteBinding(int port, int slot, Device *dev, ForceFeedbackBinding *b)
|
||||
{
|
||||
ForceFeedbackBinding *bindings = dev->pads[port][slot].ffBindings;
|
||||
int i = b - bindings;
|
||||
memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[port][slot].numFFBindings - i - 1));
|
||||
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot].numFFBindings - i - 1));
|
||||
dev->pads[port][slot].numFFBindings--;
|
||||
}
|
||||
|
||||
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo, int deadZone) {
|
||||
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo, int deadZone)
|
||||
{
|
||||
// Checks needed because I use this directly when loading bindings.
|
||||
if (port > 1 || slot>3) {
|
||||
if (port > 1 || slot > 3) {
|
||||
return -1;
|
||||
}
|
||||
if (!sensitivity) sensitivity = BASE_SENSITIVITY;
|
||||
if ((uid>>16) & (PSHBTN|TGLBTN)) {
|
||||
if (!sensitivity)
|
||||
sensitivity = BASE_SENSITIVITY;
|
||||
if ((uid >> 16) & (PSHBTN | TGLBTN)) {
|
||||
deadZone = 0;
|
||||
}
|
||||
else if (!deadZone) {
|
||||
if ((uid>>16) & PRESSURE_BTN) {
|
||||
} else if (!deadZone) {
|
||||
if ((uid >> 16) & PRESSURE_BTN) {
|
||||
deadZone = 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
deadZone = DEFAULT_DEADZONE;
|
||||
}
|
||||
}
|
||||
// Relative axes can have negative sensitivity.
|
||||
else if (((uid>>16) & 0xFF) == RELAXIS) {
|
||||
else if (((uid >> 16) & 0xFF) == RELAXIS) {
|
||||
sensitivity = abs(sensitivity);
|
||||
}
|
||||
VirtualControl *c = dev->GetVirtualControl(uid);
|
||||
if (!c) return -1;
|
||||
if (!c)
|
||||
return -1;
|
||||
// Add before deleting. Means I won't scroll up one line when scrolled down to bottom.
|
||||
int controlIndex = c - dev->virtualControls;
|
||||
int index = 0;
|
||||
PadBindings *p = dev->pads[port]+slot;
|
||||
p->bindings = (Binding*) realloc(p->bindings, (p->numBindings+1) * sizeof(Binding));
|
||||
PadBindings *p = dev->pads[port] + slot;
|
||||
p->bindings = (Binding *)realloc(p->bindings, (p->numBindings + 1) * sizeof(Binding));
|
||||
for (index = p->numBindings; index > 0; index--) {
|
||||
if (p->bindings[index-1].controlIndex < controlIndex) break;
|
||||
p->bindings[index] = p->bindings[index-1];
|
||||
if (p->bindings[index - 1].controlIndex < controlIndex)
|
||||
break;
|
||||
p->bindings[index] = p->bindings[index - 1];
|
||||
}
|
||||
Binding *b = p->bindings+index;
|
||||
Binding *b = p->bindings + index;
|
||||
p->numBindings++;
|
||||
b->command = command;
|
||||
b->controlIndex = controlIndex;
|
||||
|
@ -141,7 +146,7 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int s
|
|||
index = 0;
|
||||
while (index < p->numBindings) {
|
||||
if (index == newBindingIndex) {
|
||||
index ++;
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
b = p->bindings + index;
|
||||
|
@ -149,10 +154,9 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int s
|
|||
if (config.multipleBinding) {
|
||||
if (b->controlIndex == controlIndex && b->command == command)
|
||||
nuke = 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int uid2 = dev->virtualControls[b->controlIndex].uid;
|
||||
if (b->controlIndex == controlIndex || (!((uid2^uid) & 0xFFFFFF) && ((uid|uid2) & (UID_POV | UID_AXIS))))
|
||||
if (b->controlIndex == controlIndex || (!((uid2 ^ uid) & 0xFFFFFF) && ((uid | uid2) & (UID_POV | UID_AXIS))))
|
||||
nuke = 1;
|
||||
}
|
||||
if (!nuke) {
|
||||
|
@ -166,14 +170,15 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int s
|
|||
DeleteBinding(port, slot, dev, b);
|
||||
}
|
||||
if (!config.multipleBinding) {
|
||||
for (int port2=0; port2<2; port2++) {
|
||||
for (int slot2=0; slot2<4; slot2++) {
|
||||
if (port2==(int)port && slot2 == (int)slot) continue;
|
||||
PadBindings *p = dev->pads[port2]+slot2;
|
||||
for (int i=0; i < p->numBindings; i++) {
|
||||
Binding *b = p->bindings+i;
|
||||
for (int port2 = 0; port2 < 2; port2++) {
|
||||
for (int slot2 = 0; slot2 < 4; slot2++) {
|
||||
if (port2 == (int)port && slot2 == (int)slot)
|
||||
continue;
|
||||
PadBindings *p = dev->pads[port2] + slot2;
|
||||
for (int i = 0; i < p->numBindings; i++) {
|
||||
Binding *b = p->bindings + i;
|
||||
int uid2 = dev->virtualControls[b->controlIndex].uid;
|
||||
if (b->controlIndex == controlIndex || (!((uid2^uid) & 0xFFFFFF) && ((uid|uid2) & (UID_POV | UID_AXIS)))) {
|
||||
if (b->controlIndex == controlIndex || (!((uid2 ^ uid) & 0xFFFFFF) && ((uid | uid2) & (UID_POV | UID_AXIS)))) {
|
||||
DeleteBinding(port2, slot2, dev, b);
|
||||
i--;
|
||||
}
|
||||
|
@ -210,15 +215,16 @@ const GeneralSettingsBool BoolOptionsInfo[] = {
|
|||
{L"Turbo Key Hack", 0 /*IDC_TURBO_KEY_HACK*/, 0},
|
||||
};
|
||||
|
||||
void CALLBACK PADsetSettingsDir( const char *dir )
|
||||
void CALLBACK PADsetSettingsDir(const char *dir)
|
||||
{
|
||||
CfgHelper::SetSettingsDir(dir);
|
||||
}
|
||||
|
||||
int SaveSettings(wchar_t *file=0) {
|
||||
int SaveSettings(wchar_t *file = 0)
|
||||
{
|
||||
CfgHelper cfg;
|
||||
|
||||
for (size_t i=0; i<sizeof(BoolOptionsInfo)/sizeof(BoolOptionsInfo[0]); i++) {
|
||||
for (size_t i = 0; i < sizeof(BoolOptionsInfo) / sizeof(BoolOptionsInfo[0]); i++) {
|
||||
cfg.WriteBool(L"General Settings", BoolOptionsInfo[i].name, config.bools[i]);
|
||||
}
|
||||
cfg.WriteInt(L"General Settings", L"Close Hacks", config.closeHacks);
|
||||
|
@ -226,8 +232,8 @@ int SaveSettings(wchar_t *file=0) {
|
|||
cfg.WriteInt(L"General Settings", L"Keyboard Mode", config.keyboardApi);
|
||||
cfg.WriteInt(L"General Settings", L"Mouse Mode", config.mouseApi);
|
||||
|
||||
for (int port=0; port<2; port++) {
|
||||
for (int slot=0; slot<4; slot++) {
|
||||
for (int port = 0; port < 2; port++) {
|
||||
for (int slot = 0; slot < 4; slot++) {
|
||||
wchar_t temp[50];
|
||||
wsprintf(temp, L"Pad %i %i", port, slot);
|
||||
cfg.WriteInt(temp, L"Mode", config.padConfigs[port][slot].type);
|
||||
|
@ -238,7 +244,7 @@ int SaveSettings(wchar_t *file=0) {
|
|||
if (!dm)
|
||||
return 0;
|
||||
|
||||
for (int i=0; i<dm->numDevices; i++) {
|
||||
for (int i = 0; i < dm->numDevices; i++) {
|
||||
wchar_t id[50];
|
||||
wchar_t temp[50], temp2[1000];
|
||||
wsprintfW(id, L"Device %i", i);
|
||||
|
@ -246,9 +252,11 @@ int SaveSettings(wchar_t *file=0) {
|
|||
wchar_t *name = dev->displayName;
|
||||
while (name[0] == '[') {
|
||||
wchar_t *name2 = wcschr(name, ']');
|
||||
if (!name2) break;
|
||||
name = name2+1;
|
||||
while (iswspace(name[0])) name++;
|
||||
if (!name2)
|
||||
break;
|
||||
name = name2 + 1;
|
||||
while (iswspace(name[0]))
|
||||
name++;
|
||||
}
|
||||
|
||||
cfg.WriteStr(id, L"Display Name", name);
|
||||
|
@ -260,22 +268,22 @@ int SaveSettings(wchar_t *file=0) {
|
|||
cfg.WriteInt(id, L"Type", dev->type);
|
||||
int ffBindingCount = 0;
|
||||
int bindingCount = 0;
|
||||
for (int port=0; port<2; port++) {
|
||||
for (int slot=0; slot<4; slot++) {
|
||||
for (int j=0; j<dev->pads[port][slot].numBindings; j++) {
|
||||
Binding *b = dev->pads[port][slot].bindings+j;
|
||||
for (int port = 0; port < 2; port++) {
|
||||
for (int slot = 0; slot < 4; slot++) {
|
||||
for (int j = 0; j < dev->pads[port][slot].numBindings; j++) {
|
||||
Binding *b = dev->pads[port][slot].bindings + j;
|
||||
VirtualControl *c = &dev->virtualControls[b->controlIndex];
|
||||
wsprintfW(temp, L"Binding %i", bindingCount++);
|
||||
wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i, %i, %i", c->uid, port, b->command, b->sensitivity, b->turbo, slot, b->deadZone);
|
||||
cfg.WriteStr(id, temp, temp2);
|
||||
}
|
||||
|
||||
for (int j=0; j<dev->pads[port][slot].numFFBindings; j++) {
|
||||
ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings+j;
|
||||
for (int j = 0; j < dev->pads[port][slot].numFFBindings; j++) {
|
||||
ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings + j;
|
||||
ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex];
|
||||
wsprintfW(temp, L"FF Binding %i", ffBindingCount++);
|
||||
wsprintfW(temp2, L"%s %i, %i, %i", eff->effectID, port, b->motor, slot);
|
||||
for (int k=0; k<dev->numFFAxes; k++) {
|
||||
for (int k = 0; k < dev->numFFAxes; k++) {
|
||||
ForceFeedbackAxis *axis = dev->ffAxes + k;
|
||||
AxisEffectInfo *info = b->axes + k;
|
||||
//wsprintfW(wcschr(temp2,0), L", %i, %i", axis->id, info->force);
|
||||
|
@ -291,8 +299,10 @@ int SaveSettings(wchar_t *file=0) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int LoadSettings(int force, wchar_t *file) {
|
||||
if (dm && !force) return 0;
|
||||
int LoadSettings(int force, wchar_t *file)
|
||||
{
|
||||
if (dm && !force)
|
||||
return 0;
|
||||
|
||||
// Could just do ClearDevices() instead, but if I ever add any extra stuff,
|
||||
// this will still work.
|
||||
|
@ -301,28 +311,30 @@ int LoadSettings(int force, wchar_t *file) {
|
|||
|
||||
CfgHelper cfg;
|
||||
|
||||
for (size_t i=0; i<sizeof(BoolOptionsInfo)/sizeof(BoolOptionsInfo[0]); i++) {
|
||||
for (size_t i = 0; i < sizeof(BoolOptionsInfo) / sizeof(BoolOptionsInfo[0]); i++) {
|
||||
config.bools[i] = cfg.ReadBool(L"General Settings", BoolOptionsInfo[i].name, BoolOptionsInfo[i].defaultValue);
|
||||
}
|
||||
|
||||
|
||||
config.closeHacks = (u8)cfg.ReadInt(L"General Settings", L"Close Hacks");
|
||||
if (config.closeHacks&1) config.closeHacks &= ~2;
|
||||
if (config.closeHacks & 1)
|
||||
config.closeHacks &= ~2;
|
||||
|
||||
config.keyboardApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Keyboard Mode", LNX_KEYBOARD);
|
||||
if (!config.keyboardApi) config.keyboardApi = LNX_KEYBOARD;
|
||||
config.mouseApi = (DeviceAPI) cfg.ReadInt(L"General Settings", L"Mouse Mode");
|
||||
if (!config.keyboardApi)
|
||||
config.keyboardApi = LNX_KEYBOARD;
|
||||
config.mouseApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Mouse Mode");
|
||||
|
||||
for (int port=0; port<2; port++) {
|
||||
for (int slot=0; slot<4; slot++) {
|
||||
for (int port = 0; port < 2; port++) {
|
||||
for (int slot = 0; slot < 4; slot++) {
|
||||
wchar_t temp[50];
|
||||
wsprintf(temp, L"Pad %i %i", port, slot);
|
||||
config.padConfigs[port][slot].type = (PadType) cfg.ReadInt(temp, L"Mode", Dualshock2Pad);
|
||||
config.padConfigs[port][slot].type = (PadType)cfg.ReadInt(temp, L"Mode", Dualshock2Pad);
|
||||
config.padConfigs[port][slot].autoAnalog = cfg.ReadBool(temp, L"Auto Analog");
|
||||
}
|
||||
}
|
||||
|
||||
int i=0;
|
||||
int i = 0;
|
||||
int multipleBinding = config.multipleBinding;
|
||||
// Disabling multiple binding only prevents new multiple bindings.
|
||||
config.multipleBinding = 1;
|
||||
|
@ -332,7 +344,8 @@ int LoadSettings(int force, wchar_t *file) {
|
|||
wsprintfW(id, L"Device %i", i++);
|
||||
if (!cfg.ReadStr(id, L"Display Name", temp2) || !temp2[0] ||
|
||||
!cfg.ReadStr(id, L"Instance ID", temp3) || !temp3[0]) {
|
||||
if (i >= 100) break;
|
||||
if (i >= 100)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
wchar_t *id2 = 0;
|
||||
|
@ -341,7 +354,8 @@ int LoadSettings(int force, wchar_t *file) {
|
|||
|
||||
int api = cfg.ReadInt(id, L"API");
|
||||
int type = cfg.ReadInt(id, L"Type");
|
||||
if (!api || !type) continue;
|
||||
if (!api || !type)
|
||||
continue;
|
||||
|
||||
Device *dev = new Device((DeviceAPI)api, (DeviceType)type, temp2, temp3, id2);
|
||||
dev->attached = 0;
|
||||
|
@ -352,7 +366,8 @@ int LoadSettings(int force, wchar_t *file) {
|
|||
wsprintfW(temp, L"Binding %i", j++);
|
||||
if (!cfg.ReadStr(id, temp, temp2)) {
|
||||
if (j >= 100) {
|
||||
if (!last) break;
|
||||
if (!last)
|
||||
break;
|
||||
last = 0;
|
||||
}
|
||||
continue;
|
||||
|
@ -370,7 +385,8 @@ int LoadSettings(int force, wchar_t *file) {
|
|||
int len = sscanf(string, " %u , %i , %i , %i , %i , %i , %i", &uid, &port, &command, &sensitivity, &turbo, &slot, &deadZone);
|
||||
if (len >= 5 && type) {
|
||||
VirtualControl *c = dev->GetVirtualControl(uid);
|
||||
if (!c) c = dev->AddVirtualControl(uid, -1);
|
||||
if (!c)
|
||||
c = dev->AddVirtualControl(uid, -1);
|
||||
if (c) {
|
||||
BindCommand(dev, uid, port, slot, command, sensitivity, turbo, deadZone);
|
||||
}
|
||||
|
@ -381,7 +397,8 @@ int LoadSettings(int force, wchar_t *file) {
|
|||
wsprintfW(temp, L"FF Binding %i", j++);
|
||||
if (!cfg.ReadStr(id, temp, temp2)) {
|
||||
if (j >= 10) {
|
||||
if (!last) break;
|
||||
if (!last)
|
||||
break;
|
||||
last = 0;
|
||||
}
|
||||
continue;
|
||||
|
@ -399,8 +416,9 @@ int LoadSettings(int force, wchar_t *file) {
|
|||
// wcstok not in ntdll. More effore than its worth to shave off
|
||||
// whitespace without it.
|
||||
if (sscanf(string, " %s %i , %i , %i", effect, &port, &motor, &slot) == 4) {
|
||||
char *s = strchr(strchr(strchr(string, ',')+1, ',')+1, ',');
|
||||
if (!s) continue;
|
||||
char *s = strchr(strchr(strchr(string, ',') + 1, ',') + 1, ',');
|
||||
if (!s)
|
||||
continue;
|
||||
s++;
|
||||
w = 0;
|
||||
while (effect[w]) {
|
||||
|
@ -448,14 +466,16 @@ int LoadSettings(int force, wchar_t *file) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void UnloadConfigs() {
|
||||
void UnloadConfigs()
|
||||
{
|
||||
if (dm) {
|
||||
delete dm;
|
||||
dm = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshEnabledDevices(int updateDeviceList) {
|
||||
void RefreshEnabledDevices(int updateDeviceList)
|
||||
{
|
||||
// Clears all device state.
|
||||
static int lastXInputState = -1;
|
||||
if (updateDeviceList || lastXInputState != config.gameApis.xInput) {
|
||||
|
@ -463,12 +483,12 @@ void RefreshEnabledDevices(int updateDeviceList) {
|
|||
lastXInputState = config.gameApis.xInput;
|
||||
}
|
||||
|
||||
for (int i=0; i<dm->numDevices; i++) {
|
||||
for (int i = 0; i < dm->numDevices; i++) {
|
||||
Device *dev = dm->devices[i];
|
||||
|
||||
// XXX windows magic?
|
||||
if (!dev->attached && dev->displayName[0] != '[') {
|
||||
wchar_t *newName = (wchar_t*) malloc(sizeof(wchar_t) * (wcslen(dev->displayName) + 12));
|
||||
wchar_t *newName = (wchar_t *)malloc(sizeof(wchar_t) * (wcslen(dev->displayName) + 12));
|
||||
wsprintfW(newName, L"[Detached] %s", dev->displayName);
|
||||
free(dev->displayName);
|
||||
dev->displayName = newName;
|
||||
|
@ -499,7 +519,8 @@ void RefreshEnabledDevices(int updateDeviceList) {
|
|||
}
|
||||
}
|
||||
|
||||
void Configure() {
|
||||
void Configure()
|
||||
{
|
||||
// Can end up here without PADinit() being called first.
|
||||
LoadSettings();
|
||||
// Can also end up here after running emulator a bit, and possibly
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
wxString CfgHelper::m_path = L"inis/LilyPad.ini";
|
||||
|
||||
void CfgHelper::SetSettingsDir(const char* dir)
|
||||
void CfgHelper::SetSettingsDir(const char *dir)
|
||||
{
|
||||
m_path = wxString::FromAscii(dir) + L"/LilyPad.ini";
|
||||
}
|
||||
|
@ -37,37 +37,37 @@ CfgHelper::~CfgHelper()
|
|||
delete m_config;
|
||||
}
|
||||
|
||||
void CfgHelper::setIni(const wchar_t* Section)
|
||||
void CfgHelper::setIni(const wchar_t *Section)
|
||||
{
|
||||
m_config->SetPath(wxsFormat(L"/%s", Section));
|
||||
}
|
||||
|
||||
|
||||
void CfgHelper::WriteBool(const wchar_t* Section, const wchar_t* Name, bool Value)
|
||||
void CfgHelper::WriteBool(const wchar_t *Section, const wchar_t *Name, bool Value)
|
||||
{
|
||||
setIni(Section);
|
||||
m_config->Write(Name, Value);
|
||||
}
|
||||
|
||||
void CfgHelper::WriteInt(const wchar_t* Section, const wchar_t* Name, int Value)
|
||||
void CfgHelper::WriteInt(const wchar_t *Section, const wchar_t *Name, int Value)
|
||||
{
|
||||
setIni(Section);
|
||||
m_config->Write(Name, Value);
|
||||
}
|
||||
|
||||
void CfgHelper::WriteFloat(const wchar_t* Section, const wchar_t* Name, float Value)
|
||||
void CfgHelper::WriteFloat(const wchar_t *Section, const wchar_t *Name, float Value)
|
||||
{
|
||||
setIni(Section);
|
||||
m_config->Write(Name, (double)Value);
|
||||
}
|
||||
|
||||
void CfgHelper::WriteStr(const wchar_t* Section, const wchar_t* Name, const wxString& Data)
|
||||
void CfgHelper::WriteStr(const wchar_t *Section, const wchar_t *Name, const wxString &Data)
|
||||
{
|
||||
setIni(Section);
|
||||
m_config->Write(Name, Data);
|
||||
}
|
||||
|
||||
bool CfgHelper::ReadBool(const wchar_t *Section,const wchar_t* Name, bool Default)
|
||||
bool CfgHelper::ReadBool(const wchar_t *Section, const wchar_t *Name, bool Default)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
|
@ -77,7 +77,7 @@ bool CfgHelper::ReadBool(const wchar_t *Section,const wchar_t* Name, bool Defaul
|
|||
return ret;
|
||||
}
|
||||
|
||||
int CfgHelper::ReadInt(const wchar_t* Section, const wchar_t* Name,int Default)
|
||||
int CfgHelper::ReadInt(const wchar_t *Section, const wchar_t *Name, int Default)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -87,7 +87,7 @@ int CfgHelper::ReadInt(const wchar_t* Section, const wchar_t* Name,int Default)
|
|||
return ret;
|
||||
}
|
||||
|
||||
float CfgHelper::ReadFloat(const wchar_t* Section, const wchar_t* Name, float Default)
|
||||
float CfgHelper::ReadFloat(const wchar_t *Section, const wchar_t *Name, float Default)
|
||||
{
|
||||
double ret;
|
||||
|
||||
|
@ -97,14 +97,14 @@ float CfgHelper::ReadFloat(const wchar_t* Section, const wchar_t* Name, float De
|
|||
return (float)ret;
|
||||
}
|
||||
|
||||
int CfgHelper::ReadStr(const wchar_t* Section, const wchar_t* Name, wchar_t* Data, const wchar_t* Default)
|
||||
int CfgHelper::ReadStr(const wchar_t *Section, const wchar_t *Name, wchar_t *Data, const wchar_t *Default)
|
||||
{
|
||||
setIni(Section);
|
||||
wcscpy(Data, m_config->Read(Name, Default).wc_str());
|
||||
return wcslen(Data);
|
||||
}
|
||||
|
||||
int CfgHelper::ReadStr(const wchar_t* Section, const wchar_t* Name, wxString& Data, const wchar_t* Default)
|
||||
int CfgHelper::ReadStr(const wchar_t *Section, const wchar_t *Name, wxString &Data, const wchar_t *Default)
|
||||
{
|
||||
setIni(Section);
|
||||
Data = m_config->Read(Name, Default);
|
||||
|
|
|
@ -20,29 +20,29 @@
|
|||
#include "Global.h"
|
||||
#include <wx/fileconf.h>
|
||||
|
||||
extern void CfgSetSettingsDir(const char* dir);
|
||||
extern void CfgSetSettingsDir(const char *dir);
|
||||
|
||||
class CfgHelper {
|
||||
wxFileConfig* m_config;
|
||||
class CfgHelper
|
||||
{
|
||||
wxFileConfig *m_config;
|
||||
static wxString m_path;
|
||||
|
||||
void setIni(const wchar_t* Section);
|
||||
void setIni(const wchar_t *Section);
|
||||
|
||||
public:
|
||||
public:
|
||||
CfgHelper();
|
||||
~CfgHelper();
|
||||
|
||||
void WriteBool(const wchar_t* Section, const wchar_t* Name, bool Value);
|
||||
void WriteInt(const wchar_t* Section, const wchar_t* Name, int Value);
|
||||
void WriteFloat(const wchar_t* Section, const wchar_t* Name, float Value);
|
||||
void WriteStr(const wchar_t* Section, const wchar_t* Name, const wxString& Data);
|
||||
void WriteBool(const wchar_t *Section, const wchar_t *Name, bool Value);
|
||||
void WriteInt(const wchar_t *Section, const wchar_t *Name, int Value);
|
||||
void WriteFloat(const wchar_t *Section, const wchar_t *Name, float Value);
|
||||
void WriteStr(const wchar_t *Section, const wchar_t *Name, const wxString &Data);
|
||||
|
||||
bool ReadBool(const wchar_t *Section,const wchar_t* Name, bool Default = false);
|
||||
int ReadStr(const wchar_t* Section, const wchar_t* Name, wxString& Data, const wchar_t* Default = 0);
|
||||
int ReadStr(const wchar_t* Section, const wchar_t* Name, wchar_t* Data, const wchar_t* Default = 0);
|
||||
int ReadInt(const wchar_t* Section, const wchar_t* Name,int Default = 0);
|
||||
float ReadFloat(const wchar_t* Section, const wchar_t* Name, float Default = 0.0f);
|
||||
|
||||
static void SetSettingsDir(const char* dir);
|
||||
bool ReadBool(const wchar_t *Section, const wchar_t *Name, bool Default = false);
|
||||
int ReadStr(const wchar_t *Section, const wchar_t *Name, wxString &Data, const wchar_t *Default = 0);
|
||||
int ReadStr(const wchar_t *Section, const wchar_t *Name, wchar_t *Data, const wchar_t *Default = 0);
|
||||
int ReadInt(const wchar_t *Section, const wchar_t *Name, int Default = 0);
|
||||
float ReadFloat(const wchar_t *Section, const wchar_t *Name, float Default = 0.0f);
|
||||
|
||||
static void SetSettingsDir(const char *dir);
|
||||
};
|
||||
|
|
|
@ -20,7 +20,10 @@
|
|||
#include "Linux/JoyEvdev.h"
|
||||
#include "Linux/bitmaskros.h"
|
||||
|
||||
JoyEvdev::JoyEvdev(int fd, bool ds3, const wchar_t *id) : Device(LNX_JOY, OTHER, id, id), m_fd(fd) {
|
||||
JoyEvdev::JoyEvdev(int fd, bool ds3, const wchar_t *id)
|
||||
: Device(LNX_JOY, OTHER, id, id)
|
||||
, m_fd(fd)
|
||||
{
|
||||
// XXX LNX_JOY => DS3 or ???
|
||||
|
||||
m_abs.clear();
|
||||
|
@ -91,21 +94,24 @@ JoyEvdev::JoyEvdev(int fd, bool ds3, const wchar_t *id) : Device(LNX_JOY, OTHER,
|
|||
fprintf(stderr, "New device created. Found axe:%zu, buttons:%zu, m_rel:%zu\n\n", m_abs.size(), m_btn.size(), m_rel.size());
|
||||
}
|
||||
|
||||
JoyEvdev::~JoyEvdev() {
|
||||
JoyEvdev::~JoyEvdev()
|
||||
{
|
||||
close(m_fd);
|
||||
}
|
||||
|
||||
int JoyEvdev::Activate(InitInfo* args) {
|
||||
int JoyEvdev::Activate(InitInfo *args)
|
||||
{
|
||||
AllocState();
|
||||
|
||||
uint16_t size = m_abs.size()+m_rel.size()+m_btn.size();
|
||||
memset(physicalControlState, 0, sizeof(int)*size);
|
||||
uint16_t size = m_abs.size() + m_rel.size() + m_btn.size();
|
||||
memset(physicalControlState, 0, sizeof(int) * size);
|
||||
|
||||
active = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int JoyEvdev::Update() {
|
||||
int JoyEvdev::Update()
|
||||
{
|
||||
struct input_event events[32];
|
||||
int len;
|
||||
int status = 0;
|
||||
|
@ -116,9 +122,8 @@ int JoyEvdev::Update() {
|
|||
int evt_nb = len / sizeof(input_event);
|
||||
//fprintf(stderr, "Poll %d events available\n", evt_nb);
|
||||
for (int i = 0; i < evt_nb; i++) {
|
||||
switch(events[i].type) {
|
||||
case EV_ABS:
|
||||
{
|
||||
switch (events[i].type) {
|
||||
case EV_ABS: {
|
||||
for (size_t idx = 0; idx < m_abs.size(); idx++) {
|
||||
if (m_abs[idx].code == events[i].code) {
|
||||
// XXX strict or not ?
|
||||
|
@ -131,10 +136,8 @@ int JoyEvdev::Update() {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EV_KEY:
|
||||
{
|
||||
} break;
|
||||
case EV_KEY: {
|
||||
for (size_t idx = 0; idx < m_btn.size(); idx++) {
|
||||
if (m_btn[idx] == events[i].code) {
|
||||
fprintf(stderr, "Event KEY:%d detected with value %d\n", events[i].code, events[i].value);
|
||||
|
@ -144,8 +147,7 @@ int JoyEvdev::Update() {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case EV_REL:
|
||||
// XXX
|
||||
break;
|
||||
|
@ -153,14 +155,14 @@ int JoyEvdev::Update() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static std::wstring CorrectJoySupport(int fd) {
|
||||
static std::wstring CorrectJoySupport(int fd)
|
||||
{
|
||||
struct input_id id;
|
||||
if (ioctl(fd, EVIOCGID, &id) < 0) {
|
||||
fprintf(stderr, "Invalid IOCTL EVIOCGID\n");
|
||||
|
@ -180,7 +182,8 @@ static std::wstring CorrectJoySupport(int fd) {
|
|||
return std::wstring(s.begin(), s.end());
|
||||
}
|
||||
|
||||
void EnumJoystickEvdev() {
|
||||
void EnumJoystickEvdev()
|
||||
{
|
||||
// Technically it must be done with udev but another lib for
|
||||
// avoid a loop is too much for me (even if udev is mandatory
|
||||
// so maybe later)
|
||||
|
@ -204,5 +207,4 @@ void EnumJoystickEvdev() {
|
|||
} else if (fd >= 0)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
struct abs_info {
|
||||
struct abs_info
|
||||
{
|
||||
uint16_t code;
|
||||
int32_t min;
|
||||
int32_t max;
|
||||
|
@ -31,46 +32,52 @@ struct abs_info {
|
|||
int32_t factor;
|
||||
int32_t translation;
|
||||
|
||||
abs_info(int32_t _code, int32_t _min, int32_t _max, ControlType type) : code(_code), min(_min), max(_max) {
|
||||
abs_info(int32_t _code, int32_t _min, int32_t _max, ControlType type)
|
||||
: code(_code)
|
||||
, min(_min)
|
||||
, max(_max)
|
||||
{
|
||||
translation = 0;
|
||||
// Note: ABSAXIS ranges from -64K to 64K
|
||||
// Note: PSHBTN ranges from 0 to 64K
|
||||
if ((min == 0) && (max == 255)) {
|
||||
if (type == ABSAXIS) {
|
||||
translation = 128;
|
||||
factor = FULLY_DOWN/128;
|
||||
factor = FULLY_DOWN / 128;
|
||||
} else {
|
||||
factor = FULLY_DOWN/256;
|
||||
factor = FULLY_DOWN / 256;
|
||||
}
|
||||
} else if ((min == -1) && (max == 1)) {
|
||||
factor = FULLY_DOWN;
|
||||
} else if ((min == 0) && (std::abs(max - 127) < 2)) {
|
||||
translation = 64;
|
||||
factor = -FULLY_DOWN/64;
|
||||
factor = -FULLY_DOWN / 64;
|
||||
} else if ((max == 255) && (std::abs(min - 127) < 2)) {
|
||||
translation = 64+128;
|
||||
factor = FULLY_DOWN/64;
|
||||
translation = 64 + 128;
|
||||
factor = FULLY_DOWN / 64;
|
||||
} else {
|
||||
fprintf(stderr, "Scale not supported\n");
|
||||
factor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int scale(int32_t value) {
|
||||
int scale(int32_t value)
|
||||
{
|
||||
return (value - translation) * factor;
|
||||
}
|
||||
};
|
||||
|
||||
class JoyEvdev : public Device {
|
||||
class JoyEvdev : public Device
|
||||
{
|
||||
int m_fd;
|
||||
std::vector<abs_info> m_abs;
|
||||
std::vector<uint16_t> m_btn;
|
||||
std::vector<uint16_t> m_rel;
|
||||
|
||||
public:
|
||||
public:
|
||||
JoyEvdev(int fd, bool ds3, const wchar_t *id);
|
||||
~JoyEvdev();
|
||||
int Activate(InitInfo* args);
|
||||
int Activate(InitInfo *args);
|
||||
int Update();
|
||||
};
|
||||
|
||||
|
|
|
@ -20,15 +20,16 @@
|
|||
// actually it is even more but it is enough to distinguish different key
|
||||
#define MAX_KEYCODE (0xFF)
|
||||
|
||||
LinuxKeyboard::LinuxKeyboard() :
|
||||
Device(LNX_KEYBOARD, KEYBOARD, L"displayName", L"instanceID", L"deviceID")
|
||||
LinuxKeyboard::LinuxKeyboard()
|
||||
: Device(LNX_KEYBOARD, KEYBOARD, L"displayName", L"instanceID", L"deviceID")
|
||||
{
|
||||
for (int i=0; i<MAX_KEYCODE; i++) {
|
||||
for (int i = 0; i < MAX_KEYCODE; i++) {
|
||||
AddPhysicalControl(PSHBTN, i, i);
|
||||
}
|
||||
}
|
||||
|
||||
int LinuxKeyboard::Activate(InitInfo* args) {
|
||||
int LinuxKeyboard::Activate(InitInfo *args)
|
||||
{
|
||||
// Always active
|
||||
active = 1;
|
||||
|
||||
|
@ -45,12 +46,13 @@ int LinuxKeyboard::Activate(InitInfo* args) {
|
|||
}
|
||||
#endif
|
||||
// Every button released
|
||||
memset(physicalControlState, 0, sizeof(int)*MAX_KEYCODE);
|
||||
memset(physicalControlState, 0, sizeof(int) * MAX_KEYCODE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LinuxKeyboard::Update() {
|
||||
int LinuxKeyboard::Update()
|
||||
{
|
||||
keyEvent event;
|
||||
int status = 0;
|
||||
while (R_GetQueuedKeyEvent(&event)) {
|
||||
|
@ -73,6 +75,7 @@ int LinuxKeyboard::Update() {
|
|||
return status; // XXX ????
|
||||
}
|
||||
|
||||
void EnumLnx() {
|
||||
void EnumLnx()
|
||||
{
|
||||
dm->AddDevice(new LinuxKeyboard());
|
||||
}
|
||||
|
|
|
@ -19,10 +19,11 @@
|
|||
#include "InputManager.h"
|
||||
#include "KeyboardQueue.h"
|
||||
|
||||
class LinuxKeyboard : public Device {
|
||||
public:
|
||||
class LinuxKeyboard : public Device
|
||||
{
|
||||
public:
|
||||
LinuxKeyboard();
|
||||
int Activate(InitInfo* args);
|
||||
int Activate(InitInfo *args);
|
||||
int Update();
|
||||
};
|
||||
|
||||
|
|
|
@ -32,7 +32,8 @@ static u8 R_lastQueuedEvent = 0;
|
|||
static u8 R_nextQueuedEvent = 0;
|
||||
static keyEvent R_queuedEvents[R_EVENT_QUEUE_LEN];
|
||||
|
||||
void R_QueueKeyEvent(const keyEvent &evt) {
|
||||
void R_QueueKeyEvent(const keyEvent &evt)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(core_event);
|
||||
|
||||
R_queuedEvents[R_lastQueuedEvent] = evt;
|
||||
|
@ -41,8 +42,10 @@ void R_QueueKeyEvent(const keyEvent &evt) {
|
|||
assert(R_nextQueuedEvent != R_lastQueuedEvent);
|
||||
}
|
||||
|
||||
int R_GetQueuedKeyEvent(keyEvent *event) {
|
||||
if (R_lastQueuedEvent == R_nextQueuedEvent) return 0;
|
||||
int R_GetQueuedKeyEvent(keyEvent *event)
|
||||
{
|
||||
if (R_lastQueuedEvent == R_nextQueuedEvent)
|
||||
return 0;
|
||||
|
||||
std::lock_guard<std::mutex> lock(core_event);
|
||||
*event = R_queuedEvents[R_nextQueuedEvent];
|
||||
|
@ -50,11 +53,13 @@ int R_GetQueuedKeyEvent(keyEvent *event) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void R_ClearKeyQueue() {
|
||||
void R_ClearKeyQueue()
|
||||
{
|
||||
R_lastQueuedEvent = R_nextQueuedEvent;
|
||||
}
|
||||
|
||||
EXPORT_C_(void) PADWriteEvent(keyEvent &evt)
|
||||
EXPORT_C_(void)
|
||||
PADWriteEvent(keyEvent &evt)
|
||||
{
|
||||
R_QueueKeyEvent(evt);
|
||||
}
|
||||
|
|
|
@ -24,17 +24,17 @@
|
|||
#define nBitsPerUchar (sizeof(unsigned char) * 8)
|
||||
|
||||
/* Number of unsigned chars to contain a given number of bits */
|
||||
#define nUcharsForNBits(nBits) ((((nBits)-1)/nBitsPerUchar)+1)
|
||||
#define nUcharsForNBits(nBits) ((((nBits)-1) / nBitsPerUchar) + 1)
|
||||
|
||||
/* Index=Offset of given bit in 1 unsigned char */
|
||||
#define bitOffsetInUchar(bit) ((bit)%nBitsPerUchar)
|
||||
#define bitOffsetInUchar(bit) ((bit) % nBitsPerUchar)
|
||||
|
||||
/* Index=Offset of the unsigned char associated to the bit
|
||||
at the given index=offset */
|
||||
#define ucharIndexForBit(bit) ((bit)/nBitsPerUchar)
|
||||
#define ucharIndexForBit(bit) ((bit) / nBitsPerUchar)
|
||||
|
||||
/* Value of an unsigned char with bit set at given index=offset */
|
||||
#define ucharValueForBit(bit) (((unsigned char)(1))<<bitOffsetInUchar(bit))
|
||||
#define ucharValueForBit(bit) (((unsigned char)(1)) << bitOffsetInUchar(bit))
|
||||
|
||||
/* Test the bit with given index=offset in an unsigned char array */
|
||||
#define testBit(bit, array) ((array[ucharIndexForBit(bit)] >> bitOffsetInUchar(bit)) & 1)
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output);
|
||||
|
||||
int GetRawKeyboards(HWND hWnd) {
|
||||
int GetRawKeyboards(HWND hWnd)
|
||||
{
|
||||
RAWINPUTDEVICE Rid;
|
||||
Rid.hwndTarget = hWnd;
|
||||
|
||||
|
@ -36,7 +37,8 @@ int GetRawKeyboards(HWND hWnd) {
|
|||
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
|
||||
}
|
||||
|
||||
void ReleaseRawKeyboards() {
|
||||
void ReleaseRawKeyboards()
|
||||
{
|
||||
RAWINPUTDEVICE Rid;
|
||||
Rid.hwndTarget = 0;
|
||||
|
||||
|
@ -46,7 +48,8 @@ void ReleaseRawKeyboards() {
|
|||
RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
|
||||
}
|
||||
|
||||
int GetRawMice(HWND hWnd) {
|
||||
int GetRawMice(HWND hWnd)
|
||||
{
|
||||
RAWINPUTDEVICE Rid;
|
||||
Rid.hwndTarget = hWnd;
|
||||
|
||||
|
@ -56,7 +59,8 @@ int GetRawMice(HWND hWnd) {
|
|||
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
|
||||
}
|
||||
|
||||
void ReleaseRawMice() {
|
||||
void ReleaseRawMice()
|
||||
{
|
||||
RAWINPUTDEVICE Rid;
|
||||
Rid.hwndTarget = 0;
|
||||
|
||||
|
@ -72,15 +76,19 @@ static int rawKeyboardActivatedCount = 0;
|
|||
// Same for mice.
|
||||
static int rawMouseActivatedCount = 0;
|
||||
|
||||
class RawInputKeyboard : public WindowsKeyboard {
|
||||
class RawInputKeyboard : public WindowsKeyboard
|
||||
{
|
||||
public:
|
||||
HANDLE hDevice;
|
||||
|
||||
RawInputKeyboard(HANDLE hDevice, wchar_t *name, wchar_t *instanceID=0) : WindowsKeyboard(RAW, name, instanceID) {
|
||||
RawInputKeyboard(HANDLE hDevice, wchar_t *name, wchar_t *instanceID = 0)
|
||||
: WindowsKeyboard(RAW, name, instanceID)
|
||||
{
|
||||
this->hDevice = hDevice;
|
||||
}
|
||||
|
||||
int Activate(InitInfo *initInfo) {
|
||||
int Activate(InitInfo *initInfo)
|
||||
{
|
||||
Deactivate();
|
||||
|
||||
hWndProc = initInfo->hWndProc;
|
||||
|
@ -100,11 +108,12 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
void Deactivate() {
|
||||
void Deactivate()
|
||||
{
|
||||
FreeState();
|
||||
if (active) {
|
||||
active = 0;
|
||||
rawKeyboardActivatedCount --;
|
||||
rawKeyboardActivatedCount--;
|
||||
if (!rawKeyboardActivatedCount) {
|
||||
ReleaseRawKeyboards();
|
||||
if (!rawMouseActivatedCount)
|
||||
|
@ -114,15 +123,19 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class RawInputMouse : public WindowsMouse {
|
||||
class RawInputMouse : public WindowsMouse
|
||||
{
|
||||
public:
|
||||
HANDLE hDevice;
|
||||
|
||||
RawInputMouse(HANDLE hDevice, wchar_t *name, wchar_t *instanceID=0, wchar_t *productID=0) : WindowsMouse(RAW, 0, name, instanceID, productID) {
|
||||
RawInputMouse(HANDLE hDevice, wchar_t *name, wchar_t *instanceID = 0, wchar_t *productID = 0)
|
||||
: WindowsMouse(RAW, 0, name, instanceID, productID)
|
||||
{
|
||||
this->hDevice = hDevice;
|
||||
}
|
||||
|
||||
int Activate(InitInfo *initInfo) {
|
||||
int Activate(InitInfo *initInfo)
|
||||
{
|
||||
Deactivate();
|
||||
|
||||
hWndProc = initInfo->hWndProc;
|
||||
|
@ -147,11 +160,12 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
void Deactivate() {
|
||||
void Deactivate()
|
||||
{
|
||||
FreeState();
|
||||
if (active) {
|
||||
active = 0;
|
||||
rawMouseActivatedCount --;
|
||||
rawMouseActivatedCount--;
|
||||
if (!rawMouseActivatedCount) {
|
||||
ReleaseRawMice();
|
||||
ReleaseMouseCapture();
|
||||
|
@ -163,26 +177,29 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
|
||||
ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output)
|
||||
{
|
||||
if (uMsg == WM_INPUT) {
|
||||
if (GET_RAWINPUT_CODE_WPARAM (wParam) == RIM_INPUT) {
|
||||
if (GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT) {
|
||||
RAWINPUT in;
|
||||
unsigned int size = sizeof(RAWINPUT);
|
||||
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &in, &size, sizeof(RAWINPUTHEADER)) > 0) {
|
||||
for (int i=0; i<dm->numDevices; i++) {
|
||||
for (int i = 0; i < dm->numDevices; i++) {
|
||||
Device *dev = dm->devices[i];
|
||||
if (dev->api != RAW || !dev->active) continue;
|
||||
if (dev->api != RAW || !dev->active)
|
||||
continue;
|
||||
if (in.header.dwType == RIM_TYPEKEYBOARD && dev->type == KEYBOARD) {
|
||||
RawInputKeyboard* rik = (RawInputKeyboard*)dev;
|
||||
if (rik->hDevice != in.header.hDevice) continue;
|
||||
RawInputKeyboard *rik = (RawInputKeyboard *)dev;
|
||||
if (rik->hDevice != in.header.hDevice)
|
||||
continue;
|
||||
|
||||
u32 uMsg = in.data.keyboard.Message;
|
||||
if (!(in.data.keyboard.VKey>>8))
|
||||
rik->UpdateKey((u8) in.data.keyboard.VKey, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN));
|
||||
}
|
||||
else if (in.header.dwType == RIM_TYPEMOUSE && dev->type == MOUSE) {
|
||||
RawInputMouse* rim = (RawInputMouse*)dev;
|
||||
if (rim->hDevice != in.header.hDevice) continue;
|
||||
if (!(in.data.keyboard.VKey >> 8))
|
||||
rik->UpdateKey((u8)in.data.keyboard.VKey, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN));
|
||||
} else if (in.header.dwType == RIM_TYPEMOUSE && dev->type == MOUSE) {
|
||||
RawInputMouse *rim = (RawInputMouse *)dev;
|
||||
if (rim->hDevice != in.header.hDevice)
|
||||
continue;
|
||||
if (in.data.mouse.usFlags) {
|
||||
// Never been set for me, and specs on what most of them
|
||||
// actually mean is sorely lacking. Also, specs erroneously
|
||||
|
@ -202,7 +219,7 @@ ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
|
|||
buttons >>= 2;
|
||||
}
|
||||
if (in.data.mouse.usButtonFlags & RI_MOUSE_WHEEL) {
|
||||
rim->UpdateAxis(2, ((short)in.data.mouse.usButtonData)/WHEEL_DELTA);
|
||||
rim->UpdateAxis(2, ((short)in.data.mouse.usButtonData) / WHEEL_DELTA);
|
||||
}
|
||||
if (in.data.mouse.lLastX || in.data.mouse.lLastY) {
|
||||
rim->UpdateAxis(0, in.data.mouse.lLastX);
|
||||
|
@ -212,15 +229,14 @@ ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (uMsg == WM_ACTIVATE) {
|
||||
for (int i=0; i<dm->numDevices; i++) {
|
||||
} else if (uMsg == WM_ACTIVATE) {
|
||||
for (int i = 0; i < dm->numDevices; i++) {
|
||||
Device *dev = dm->devices[i];
|
||||
if (dev->api != RAW || dev->physicalControlState == 0) continue;
|
||||
if (dev->api != RAW || dev->physicalControlState == 0)
|
||||
continue;
|
||||
memset(dev->physicalControlState, 0, sizeof(int) * dev->numPhysicalControls);
|
||||
}
|
||||
}
|
||||
else if (uMsg == WM_SIZE && rawMouseActivatedCount) {
|
||||
} else if (uMsg == WM_SIZE && rawMouseActivatedCount) {
|
||||
// Doesn't really matter for raw mice, as I disable legacy stuff, but shouldn't hurt.
|
||||
WindowsMouse::WindowResized(hWnd);
|
||||
}
|
||||
|
@ -228,23 +244,25 @@ ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
|
|||
return CONTINUE_BLISSFULLY;
|
||||
}
|
||||
|
||||
void EnumRawInputDevices() {
|
||||
void EnumRawInputDevices()
|
||||
{
|
||||
int count = 0;
|
||||
if (GetRawInputDeviceList(0, (unsigned int*)&count, sizeof(RAWINPUTDEVICELIST)) != (UINT)-1 && count > 0) {
|
||||
wchar_t *instanceID = (wchar_t *) malloc(41000*sizeof(wchar_t));
|
||||
if (GetRawInputDeviceList(0, (unsigned int *)&count, sizeof(RAWINPUTDEVICELIST)) != (UINT)-1 && count > 0) {
|
||||
wchar_t *instanceID = (wchar_t *)malloc(41000 * sizeof(wchar_t));
|
||||
wchar_t *keyName = instanceID + 11000;
|
||||
wchar_t *displayName = keyName + 10000;
|
||||
wchar_t *productID = displayName + 10000;
|
||||
|
||||
RAWINPUTDEVICELIST *list = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * count);
|
||||
RAWINPUTDEVICELIST *list = (RAWINPUTDEVICELIST *)malloc(sizeof(RAWINPUTDEVICELIST) * count);
|
||||
int keyboardCount = 1;
|
||||
int mouseCount = 1;
|
||||
count = GetRawInputDeviceList(list, (unsigned int*)&count, sizeof(RAWINPUTDEVICELIST));
|
||||
count = GetRawInputDeviceList(list, (unsigned int *)&count, sizeof(RAWINPUTDEVICELIST));
|
||||
|
||||
// Not necessary, but reminder that count is -1 on failure.
|
||||
if (count > 0) {
|
||||
for (int i=0; i<count; i++) {
|
||||
if (list[i].dwType != RIM_TYPEKEYBOARD && list[i].dwType != RIM_TYPEMOUSE) continue;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (list[i].dwType != RIM_TYPEKEYBOARD && list[i].dwType != RIM_TYPEMOUSE)
|
||||
continue;
|
||||
|
||||
UINT bufferLen = 10000;
|
||||
int nameLen = GetRawInputDeviceInfo(list[i].hDevice, RIDI_DEVICENAME, instanceID, &bufferLen);
|
||||
|
@ -256,28 +274,33 @@ void EnumRawInputDevices() {
|
|||
// and reformat it to point to registry entry containing device description.
|
||||
wcscpy(productID, instanceID);
|
||||
wchar_t *temp = 0;
|
||||
for (int j=0; j<3; j++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
wchar_t *s = wcschr(productID, '#');
|
||||
if (!s) break;
|
||||
if (!s)
|
||||
break;
|
||||
*s = '\\';
|
||||
if (j==2) {
|
||||
if (j == 2) {
|
||||
*s = 0;
|
||||
}
|
||||
if (j==1) temp = s;
|
||||
if (j == 1)
|
||||
temp = s;
|
||||
}
|
||||
|
||||
wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID+3);
|
||||
if (temp) *temp = 0;
|
||||
wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID + 3);
|
||||
if (temp)
|
||||
*temp = 0;
|
||||
int haveDescription = 0;
|
||||
HKEY hKey;
|
||||
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) {
|
||||
DWORD type;
|
||||
DWORD len = 10000 * sizeof(wchar_t);
|
||||
if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE*)displayName, &len) &&
|
||||
if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE *)displayName, &len) &&
|
||||
len && type == REG_SZ) {
|
||||
wchar_t *temp2 = wcsrchr(displayName, ';');
|
||||
if (!temp2) temp2 = displayName;
|
||||
else temp2++;
|
||||
if (!temp2)
|
||||
temp2 = displayName;
|
||||
else
|
||||
temp2++;
|
||||
// Could do without this, but more effort than it's worth.
|
||||
wcscpy(keyName, temp2);
|
||||
haveDescription = 1;
|
||||
|
@ -285,13 +308,16 @@ void EnumRawInputDevices() {
|
|||
RegCloseKey(hKey);
|
||||
}
|
||||
if (list[i].dwType == RIM_TYPEKEYBOARD) {
|
||||
if (!haveDescription) wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++);
|
||||
else wsprintfW(displayName, L"Raw KB: %s", keyName);
|
||||
if (!haveDescription)
|
||||
wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++);
|
||||
else
|
||||
wsprintfW(displayName, L"Raw KB: %s", keyName);
|
||||
dm->AddDevice(new RawInputKeyboard(list[i].hDevice, displayName, instanceID));
|
||||
}
|
||||
else if (list[i].dwType == RIM_TYPEMOUSE) {
|
||||
if (!haveDescription) wsprintfW(displayName, L"Raw Mouse %i", mouseCount++);
|
||||
else wsprintfW(displayName, L"Raw MS: %s", keyName);
|
||||
} else if (list[i].dwType == RIM_TYPEMOUSE) {
|
||||
if (!haveDescription)
|
||||
wsprintfW(displayName, L"Raw Mouse %i", mouseCount++);
|
||||
else
|
||||
wsprintfW(displayName, L"Raw MS: %s", keyName);
|
||||
dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,68 +18,91 @@
|
|||
#include "Global.h"
|
||||
#include "VKey.h"
|
||||
|
||||
wchar_t *GetVKStringW(unsigned char vk) {
|
||||
wchar_t *GetVKStringW(unsigned char vk)
|
||||
{
|
||||
int flag;
|
||||
static wchar_t t[20];
|
||||
switch(vk) {
|
||||
case 0x0C: return L"Clear";
|
||||
case 0x13: return L"Pause";
|
||||
switch (vk) {
|
||||
case 0x0C:
|
||||
return L"Clear";
|
||||
case 0x13:
|
||||
return L"Pause";
|
||||
|
||||
case 0x21:// return "Page Up";
|
||||
case 0x22:// return "Page Down";
|
||||
case 0x23:// return "End";
|
||||
case 0x24:// return "Home";
|
||||
case 0x25:// return "Left";
|
||||
case 0x26:// return "Up";
|
||||
case 0x27:// return "Right";
|
||||
case 0x28:// return "Down";
|
||||
case 0x2D:// return "Insert";
|
||||
case 0x2E:// return "Delete";
|
||||
case 0x5B:// return "Left Windows";
|
||||
case 0x5C:// return "Right Windows";
|
||||
case 0x5D:// return "Application";
|
||||
case 0x6F:// return "Num /";
|
||||
flag = 1<<24;
|
||||
case 0x21: // return "Page Up";
|
||||
case 0x22: // return "Page Down";
|
||||
case 0x23: // return "End";
|
||||
case 0x24: // return "Home";
|
||||
case 0x25: // return "Left";
|
||||
case 0x26: // return "Up";
|
||||
case 0x27: // return "Right";
|
||||
case 0x28: // return "Down";
|
||||
case 0x2D: // return "Insert";
|
||||
case 0x2E: // return "Delete";
|
||||
case 0x5B: // return "Left Windows";
|
||||
case 0x5C: // return "Right Windows";
|
||||
case 0x5D: // return "Application";
|
||||
case 0x6F: // return "Num /";
|
||||
flag = 1 << 24;
|
||||
break;
|
||||
|
||||
case 0x29: return L"Select";
|
||||
case 0x2A: return L"Print";
|
||||
case 0x2B: return L"Execute";
|
||||
case 0x2C: return L"Prnt Scrn";
|
||||
case 0x2F: return L"Help";
|
||||
case 0x29:
|
||||
return L"Select";
|
||||
case 0x2A:
|
||||
return L"Print";
|
||||
case 0x2B:
|
||||
return L"Execute";
|
||||
case 0x2C:
|
||||
return L"Prnt Scrn";
|
||||
case 0x2F:
|
||||
return L"Help";
|
||||
|
||||
case 0x6C: return L"|";
|
||||
case 0x90: return L"Num Lock";
|
||||
case 0x6C:
|
||||
return L"|";
|
||||
case 0x90:
|
||||
return L"Num Lock";
|
||||
|
||||
case 0xA0: return L"Left Shift";
|
||||
case 0xA1: return L"Right Shift";
|
||||
case 0xA2: return L"Left Ctrl";
|
||||
case 0xA3: return L"Right Ctrl";
|
||||
case 0xA4: return L"Left Alt";
|
||||
case 0xA5: return L"Right Alt";
|
||||
case 0xA0:
|
||||
return L"Left Shift";
|
||||
case 0xA1:
|
||||
return L"Right Shift";
|
||||
case 0xA2:
|
||||
return L"Left Ctrl";
|
||||
case 0xA3:
|
||||
return L"Right Ctrl";
|
||||
case 0xA4:
|
||||
return L"Left Alt";
|
||||
case 0xA5:
|
||||
return L"Right Alt";
|
||||
|
||||
case 0xA6: return L"Back";
|
||||
case 0xA7: return L"Forward";
|
||||
case 0xA8: return L"Refresh";
|
||||
case 0xA9: return L"Stop";
|
||||
case 0xAA: return L"Search";
|
||||
case 0xAB: return L"Favorites";
|
||||
case 0xAC: return L"Browser";
|
||||
case 0xA6:
|
||||
return L"Back";
|
||||
case 0xA7:
|
||||
return L"Forward";
|
||||
case 0xA8:
|
||||
return L"Refresh";
|
||||
case 0xA9:
|
||||
return L"Stop";
|
||||
case 0xAA:
|
||||
return L"Search";
|
||||
case 0xAB:
|
||||
return L"Favorites";
|
||||
case 0xAC:
|
||||
return L"Browser";
|
||||
|
||||
case 0xFA: return L"Play";
|
||||
case 0xFB: return L"Zoom";
|
||||
case 0xFA:
|
||||
return L"Play";
|
||||
case 0xFB:
|
||||
return L"Zoom";
|
||||
default:
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
int res = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
|
||||
if (res && GetKeyNameText((res<<16) | flag, t, 20)) {
|
||||
if (res && GetKeyNameText((res << 16) | flag, t, 20)) {
|
||||
// don't trust windows
|
||||
t[19] = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
wsprintfW(t, L"Key %i", vk);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,30 +21,35 @@
|
|||
#include "WindowsKeyboard.h"
|
||||
#include "KeyboardQueue.h"
|
||||
|
||||
WindowsKeyboard::WindowsKeyboard(DeviceAPI api, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID) :
|
||||
Device(api, KEYBOARD, displayName, instanceID, deviceID) {
|
||||
for (int i=0; i<256; i++) {
|
||||
WindowsKeyboard::WindowsKeyboard(DeviceAPI api, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID)
|
||||
: Device(api, KEYBOARD, displayName, instanceID, deviceID)
|
||||
{
|
||||
for (int i = 0; i < 256; i++) {
|
||||
AddPhysicalControl(PSHBTN, i, i);
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t *WindowsKeyboard::GetPhysicalControlName(PhysicalControl *control) {
|
||||
wchar_t *WindowsKeyboard::GetPhysicalControlName(PhysicalControl *control)
|
||||
{
|
||||
int id = control->id;
|
||||
if (control->type == PSHBTN && id >= 0 && id < 256) {
|
||||
wchar_t *w = GetVKStringW(id);
|
||||
if (w) return w;
|
||||
if (w)
|
||||
return w;
|
||||
}
|
||||
return Device::GetPhysicalControlName(control);
|
||||
}
|
||||
|
||||
void WindowsKeyboard::UpdateKey(int vkey, int state) {
|
||||
void WindowsKeyboard::UpdateKey(int vkey, int state)
|
||||
{
|
||||
if (vkey > 7 && vkey < 256) {
|
||||
int newState = state * FULLY_DOWN;
|
||||
if (newState != physicalControlState[vkey]) {
|
||||
// Check for alt-F4 to avoid toggling skip mode incorrectly.
|
||||
if (vkey != VK_F4 || !(physicalControlState[VK_MENU] || physicalControlState[VK_RMENU] || physicalControlState[VK_LMENU])) {
|
||||
int event = KEYPRESS;
|
||||
if (!newState) event = KEYRELEASE;
|
||||
if (!newState)
|
||||
event = KEYRELEASE;
|
||||
QueueKeyEvent(vkey, event);
|
||||
}
|
||||
}
|
||||
|
@ -52,11 +57,12 @@ void WindowsKeyboard::UpdateKey(int vkey, int state) {
|
|||
}
|
||||
}
|
||||
|
||||
void WindowsKeyboard::InitState() {
|
||||
void WindowsKeyboard::InitState()
|
||||
{
|
||||
AllocState();
|
||||
for (int vkey=5; vkey<256; vkey++) {
|
||||
int value = (unsigned short)(((short)GetAsyncKeyState(vkey))>>15);
|
||||
value += value&1;
|
||||
for (int vkey = 5; vkey < 256; vkey++) {
|
||||
int value = (unsigned short)(((short)GetAsyncKeyState(vkey)) >> 15);
|
||||
value += value & 1;
|
||||
if (vkey == VK_CONTROL || vkey == VK_MENU || vkey == VK_SHIFT) {
|
||||
value = 0;
|
||||
}
|
||||
|
|
|
@ -16,9 +16,10 @@
|
|||
*/
|
||||
|
||||
// Shared functionality for WM and RAW keyboards.
|
||||
class WindowsKeyboard : public Device {
|
||||
class WindowsKeyboard : public Device
|
||||
{
|
||||
public:
|
||||
WindowsKeyboard(DeviceAPI api, wchar_t *displayName, wchar_t *instanceID=0, wchar_t *deviceID=0);
|
||||
WindowsKeyboard(DeviceAPI api, wchar_t *displayName, wchar_t *instanceID = 0, wchar_t *deviceID = 0);
|
||||
wchar_t *GetPhysicalControlName(PhysicalControl *control);
|
||||
void UpdateKey(int vkey, int state);
|
||||
// Calls AllocState() and initializes to current keyboard state using
|
||||
|
|
|
@ -32,16 +32,20 @@ class WindowsMessagingMouse;
|
|||
static WindowsMessagingKeyboard *wmk = 0;
|
||||
static WindowsMessagingMouse *wmm = 0;
|
||||
|
||||
class WindowsMessagingKeyboard : public WindowsKeyboard {
|
||||
class WindowsMessagingKeyboard : public WindowsKeyboard
|
||||
{
|
||||
public:
|
||||
|
||||
WindowsMessagingKeyboard() : WindowsKeyboard(WM, L"WM Keyboard") {
|
||||
WindowsMessagingKeyboard()
|
||||
: WindowsKeyboard(WM, L"WM Keyboard")
|
||||
{
|
||||
}
|
||||
|
||||
int Activate(InitInfo *initInfo) {
|
||||
int Activate(InitInfo *initInfo)
|
||||
{
|
||||
// Redundant. Should match the next line.
|
||||
// Deactivate();
|
||||
if (wmk) wmk->Deactivate();
|
||||
if (wmk)
|
||||
wmk->Deactivate();
|
||||
|
||||
hWndProc = initInfo->hWndProc;
|
||||
|
||||
|
@ -55,7 +59,8 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
void Deactivate() {
|
||||
void Deactivate()
|
||||
{
|
||||
if (active) {
|
||||
if (!wmm)
|
||||
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
|
||||
|
@ -66,21 +71,26 @@ public:
|
|||
}
|
||||
|
||||
|
||||
void CheckKey(int vkey) {
|
||||
UpdateKey(vkey, 1&(((unsigned short)GetAsyncKeyState(vkey))>>15));
|
||||
void CheckKey(int vkey)
|
||||
{
|
||||
UpdateKey(vkey, 1 & (((unsigned short)GetAsyncKeyState(vkey)) >> 15));
|
||||
}
|
||||
};
|
||||
|
||||
class WindowsMessagingMouse : public WindowsMouse {
|
||||
class WindowsMessagingMouse : public WindowsMouse
|
||||
{
|
||||
public:
|
||||
|
||||
WindowsMessagingMouse() : WindowsMouse(WM, 1, L"WM Mouse") {
|
||||
WindowsMessagingMouse()
|
||||
: WindowsMouse(WM, 1, L"WM Mouse")
|
||||
{
|
||||
}
|
||||
|
||||
int Activate(InitInfo *initInfo) {
|
||||
int Activate(InitInfo *initInfo)
|
||||
{
|
||||
// Redundant. Should match the next line.
|
||||
// Deactivate();
|
||||
if (wmm) wmm->Deactivate();
|
||||
if (wmm)
|
||||
wmm->Deactivate();
|
||||
hWndProc = initInfo->hWndProc;
|
||||
|
||||
if (!wmk)
|
||||
|
@ -96,7 +106,8 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
void Deactivate() {
|
||||
void Deactivate()
|
||||
{
|
||||
if (active) {
|
||||
if (!wmk)
|
||||
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
|
||||
|
@ -108,30 +119,27 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
|
||||
ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output)
|
||||
{
|
||||
if (wmk) {
|
||||
if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN || uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP) {
|
||||
if (wParam == VK_SHIFT) {
|
||||
wmk->CheckKey(VK_RSHIFT);
|
||||
wmk->CheckKey(VK_LSHIFT);
|
||||
}
|
||||
else if (wParam == VK_CONTROL) {
|
||||
} else if (wParam == VK_CONTROL) {
|
||||
wmk->CheckKey(VK_RCONTROL);
|
||||
wmk->CheckKey(VK_LCONTROL);
|
||||
}
|
||||
else if (wParam == VK_MENU) {
|
||||
} else if (wParam == VK_MENU) {
|
||||
wmk->CheckKey(VK_RMENU);
|
||||
wmk->CheckKey(VK_LMENU);
|
||||
}
|
||||
else
|
||||
} else
|
||||
wmk->UpdateKey(wParam, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN));
|
||||
return NO_WND_PROC;
|
||||
}
|
||||
// Needed to prevent default handling of keys in some situations.
|
||||
else if (uMsg == WM_CHAR || uMsg == WM_UNICHAR) {
|
||||
return NO_WND_PROC;
|
||||
}
|
||||
else if (uMsg == WM_ACTIVATE) {
|
||||
} else if (uMsg == WM_ACTIVATE) {
|
||||
// Not really needed, but doesn't hurt.
|
||||
memset(wmk->physicalControlState, 0, sizeof(int) * wmk->numPhysicalControls);
|
||||
}
|
||||
|
@ -148,32 +156,25 @@ ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
SetCursorPos(wmm->center.x, wmm->center.y);
|
||||
}
|
||||
return NO_WND_PROC;
|
||||
}
|
||||
else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) {
|
||||
} else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) {
|
||||
wmm->UpdateButton(0, uMsg == WM_LBUTTONDOWN);
|
||||
return NO_WND_PROC;
|
||||
}
|
||||
else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) {
|
||||
} else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) {
|
||||
wmm->UpdateButton(1, uMsg == WM_RBUTTONDOWN);
|
||||
return NO_WND_PROC;
|
||||
}
|
||||
else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) {
|
||||
} else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) {
|
||||
wmm->UpdateButton(2, uMsg == WM_MBUTTONDOWN);
|
||||
return NO_WND_PROC;
|
||||
}
|
||||
else if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) {
|
||||
wmm->UpdateButton(3+((wParam>>16) == XBUTTON2), uMsg == WM_XBUTTONDOWN);
|
||||
} else if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) {
|
||||
wmm->UpdateButton(3 + ((wParam >> 16) == XBUTTON2), uMsg == WM_XBUTTONDOWN);
|
||||
return NO_WND_PROC;
|
||||
}
|
||||
else if (uMsg == WM_MOUSEWHEEL) {
|
||||
wmm->UpdateAxis(2, ((int)wParam>>16)/WHEEL_DELTA);
|
||||
} else if (uMsg == WM_MOUSEWHEEL) {
|
||||
wmm->UpdateAxis(2, ((int)wParam >> 16) / WHEEL_DELTA);
|
||||
return NO_WND_PROC;
|
||||
}
|
||||
else if (uMsg == WM_MOUSEHWHEEL) {
|
||||
wmm->UpdateAxis(3, ((int)wParam>>16)/WHEEL_DELTA);
|
||||
} else if (uMsg == WM_MOUSEHWHEEL) {
|
||||
wmm->UpdateAxis(3, ((int)wParam >> 16) / WHEEL_DELTA);
|
||||
return NO_WND_PROC;
|
||||
}
|
||||
else if (uMsg == WM_SIZE && wmm->active) {
|
||||
} else if (uMsg == WM_SIZE && wmm->active) {
|
||||
WindowsMouse::WindowResized(hWnd);
|
||||
}
|
||||
// Taken care of elsewhere. When binding, killing focus means stop reading input.
|
||||
|
@ -185,7 +186,8 @@ ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
return CONTINUE_BLISSFULLY;
|
||||
}
|
||||
|
||||
void EnumWindowsMessagingDevices() {
|
||||
void EnumWindowsMessagingDevices()
|
||||
{
|
||||
dm->AddDevice(new WindowsMessagingKeyboard());
|
||||
dm->AddDevice(new WindowsMessagingMouse());
|
||||
}
|
||||
|
|
|
@ -23,19 +23,21 @@
|
|||
POINT WindowsMouse::origCursorPos;
|
||||
POINT WindowsMouse::center;
|
||||
|
||||
WindowsMouse::WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID) :
|
||||
Device(api, MOUSE, displayName, instanceID, deviceID) {
|
||||
WindowsMouse::WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID)
|
||||
: Device(api, MOUSE, displayName, instanceID, deviceID)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<5; i++) {
|
||||
for (i = 0; i < 5; i++) {
|
||||
AddPhysicalControl(PSHBTN, i, i);
|
||||
}
|
||||
|
||||
for (i=0; i<3+hWheel; i++) {
|
||||
AddPhysicalControl(RELAXIS, i+5, i+5);
|
||||
for (i = 0; i < 3 + hWheel; i++) {
|
||||
AddPhysicalControl(RELAXIS, i + 5, i + 5);
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t *WindowsMouse::GetPhysicalControlName(PhysicalControl *control) {
|
||||
wchar_t *WindowsMouse::GetPhysicalControlName(PhysicalControl *control)
|
||||
{
|
||||
wchar_t *names[9] = {
|
||||
L"L Button",
|
||||
L"R Button",
|
||||
|
@ -45,33 +47,39 @@ wchar_t *WindowsMouse::GetPhysicalControlName(PhysicalControl *control) {
|
|||
L"X Axis",
|
||||
L"Y Axis",
|
||||
L"Y Wheel",
|
||||
L"X Wheel"
|
||||
};
|
||||
if (control->id < 9) return names[control->id];
|
||||
L"X Wheel"};
|
||||
if (control->id < 9)
|
||||
return names[control->id];
|
||||
return Device::GetPhysicalControlName(control);
|
||||
}
|
||||
|
||||
void WindowsMouse::UpdateButton(unsigned int button, int state) {
|
||||
if (button > 4) return;
|
||||
void WindowsMouse::UpdateButton(unsigned int button, int state)
|
||||
{
|
||||
if (button > 4)
|
||||
return;
|
||||
physicalControlState[button] = (state << 16);
|
||||
}
|
||||
|
||||
void WindowsMouse::UpdateAxis(unsigned int axis, int delta) {
|
||||
if (axis > 3) return;
|
||||
void WindowsMouse::UpdateAxis(unsigned int axis, int delta)
|
||||
{
|
||||
if (axis > 3)
|
||||
return;
|
||||
// 1 mouse pixel = 1/8th way down.
|
||||
physicalControlState[5+axis] += (delta<<(16 - 3*(axis < 2)));
|
||||
physicalControlState[5 + axis] += (delta << (16 - 3 * (axis < 2)));
|
||||
}
|
||||
|
||||
void WindowsMouse::WindowResized(HWND hWnd) {
|
||||
void WindowsMouse::WindowResized(HWND hWnd)
|
||||
{
|
||||
RECT r;
|
||||
GetWindowRect(hWnd, &r);
|
||||
ClipCursor(&r);
|
||||
center.x = (r.left + r.right)/2;
|
||||
center.y = (r.top + r.bottom)/2;
|
||||
center.x = (r.left + r.right) / 2;
|
||||
center.y = (r.top + r.bottom) / 2;
|
||||
SetCursorPos(center.x, center.y);
|
||||
}
|
||||
|
||||
void WindowsMouse::GetMouseCapture(HWND hWnd) {
|
||||
void WindowsMouse::GetMouseCapture(HWND hWnd)
|
||||
{
|
||||
SetCapture(hWnd);
|
||||
ShowCursor(0);
|
||||
|
||||
|
@ -80,12 +88,13 @@ void WindowsMouse::GetMouseCapture(HWND hWnd) {
|
|||
RECT r;
|
||||
GetWindowRect(hWnd, &r);
|
||||
ClipCursor(&r);
|
||||
center.x = (r.left + r.right)/2;
|
||||
center.y = (r.top + r.bottom)/2;
|
||||
center.x = (r.left + r.right) / 2;
|
||||
center.y = (r.top + r.bottom) / 2;
|
||||
SetCursorPos(center.x, center.y);
|
||||
}
|
||||
|
||||
void WindowsMouse::ReleaseMouseCapture() {
|
||||
void WindowsMouse::ReleaseMouseCapture()
|
||||
{
|
||||
ClipCursor(0);
|
||||
ReleaseCapture();
|
||||
ShowCursor(1);
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
*/
|
||||
|
||||
// Shared functionality for WM and RAW keyboards.
|
||||
class WindowsMouse : public Device {
|
||||
class WindowsMouse : public Device
|
||||
{
|
||||
public:
|
||||
// Used by GetMouseCapture()/ReleaseMouseCapture()
|
||||
// Static because can have multiple raw mice active at once,
|
||||
|
@ -30,7 +31,7 @@ public:
|
|||
|
||||
// hWheel variable lets me display no horizontal wheel for raw input, just to make it clear
|
||||
// that it's not supported.
|
||||
WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID=0, wchar_t *deviceID=0);
|
||||
WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID = 0, wchar_t *deviceID = 0);
|
||||
wchar_t *GetPhysicalControlName(PhysicalControl *control);
|
||||
// State is 0 for up, 1 for down.
|
||||
void UpdateButton(unsigned int button, int state);
|
||||
|
|
|
@ -37,13 +37,15 @@ WndProcEater::~WndProcEater() throw()
|
|||
}
|
||||
}
|
||||
|
||||
void WndProcEater::ReleaseExtraProc(ExtraWndProc proc) {
|
||||
void WndProcEater::ReleaseExtraProc(ExtraWndProc proc)
|
||||
{
|
||||
// Probably isn't needed, but just in case...
|
||||
if (hMutex) WaitForSingleObject(hMutex, 100);
|
||||
if (hMutex)
|
||||
WaitForSingleObject(hMutex, 100);
|
||||
|
||||
//printf( "(Lilypad) Regurgitating! -> 0x%x\n", proc );
|
||||
|
||||
for (int i=0; i<numExtraProcs; i++) {
|
||||
for (int i = 0; i < numExtraProcs; i++) {
|
||||
if (extraProcs[i].proc == proc) {
|
||||
extraProcs[i] = extraProcs[--numExtraProcs];
|
||||
break;
|
||||
|
@ -57,8 +59,10 @@ void WndProcEater::ReleaseExtraProc(ExtraWndProc proc) {
|
|||
}
|
||||
}
|
||||
|
||||
void WndProcEater::Release() {
|
||||
while (numExtraProcs) ReleaseExtraProc(extraProcs[0].proc);
|
||||
void WndProcEater::Release()
|
||||
{
|
||||
while (numExtraProcs)
|
||||
ReleaseExtraProc(extraProcs[0].proc);
|
||||
if (hWndEaten && IsWindow(hWndEaten)) {
|
||||
RemoveProp(hWndEaten, L"LilyHaxxor");
|
||||
SetWindowLongPtr(hWndEaten, GWLP_WNDPROC, (LONG_PTR)eatenWndProc);
|
||||
|
@ -69,8 +73,8 @@ void WndProcEater::Release() {
|
|||
|
||||
LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if( hWnd != hWndEaten )
|
||||
fprintf( stderr, "Totally mismatched window handles on OverrideWndProc!\n" );
|
||||
if (hWnd != hWndEaten)
|
||||
fprintf(stderr, "Totally mismatched window handles on OverrideWndProc!\n");
|
||||
|
||||
ExtraWndProcResult res = CONTINUE_BLISSFULLY;
|
||||
LRESULT out = 0;
|
||||
|
@ -79,7 +83,7 @@ LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
|
|||
return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
for (int i=0; i<numExtraProcs; i++) {
|
||||
for (int i = 0; i < numExtraProcs; i++) {
|
||||
// Note: Second bit of deviceUpdateQueued is only set when I receive a device change
|
||||
// notification, which is handled in the GS thread in one of the extraProcs, so this
|
||||
// is all I need to prevent bad things from happening while updating devices. No mutex needed.
|
||||
|
@ -90,8 +94,8 @@ LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
|
|||
if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) {
|
||||
ReleaseExtraProc(extraProcs[i].proc);
|
||||
i--;
|
||||
}
|
||||
else if (res2 > res) res = res2;
|
||||
} else if (res2 > res)
|
||||
res = res2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,38 +113,42 @@ LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
|
|||
|
||||
static LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
WndProcEater* obj = (WndProcEater*)GetProp(hWnd, L"LilyHaxxor");
|
||||
WndProcEater *obj = (WndProcEater *)GetProp(hWnd, L"LilyHaxxor");
|
||||
return (obj == NULL) ?
|
||||
DefWindowProc(hWnd, uMsg, wParam, lParam) :
|
||||
obj->_OverrideWndProc( hWnd, uMsg, wParam, lParam );
|
||||
obj->_OverrideWndProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
bool WndProcEater::SetWndHandle(HWND hWnd)
|
||||
{
|
||||
if(hWnd == hWndEaten) return true;
|
||||
if (hWnd == hWndEaten)
|
||||
return true;
|
||||
|
||||
//printf( "(Lilypad) (Re)-Setting window handle! -> this=0x%08x, hWnd=0x%08x\n", this, hWnd );
|
||||
|
||||
Release();
|
||||
SetProp(hWnd, L"LilyHaxxor", (HANDLE)this);
|
||||
SetProp(hWnd, L"LilyHaxxor", (HANDLE) this);
|
||||
|
||||
eatenWndProc = (WNDPROC) SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)OverrideWndProc);
|
||||
eatenWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)OverrideWndProc);
|
||||
hWndEaten = (eatenWndProc) ? hWnd : 0;
|
||||
|
||||
return !!hWndEaten;
|
||||
}
|
||||
|
||||
void WndProcEater::Eat(ExtraWndProc proc, DWORD flags) {
|
||||
void WndProcEater::Eat(ExtraWndProc proc, DWORD flags)
|
||||
{
|
||||
|
||||
// check if Subclassing failed to init during SetWndHandle
|
||||
if (!hWndEaten) return;
|
||||
if (!hWndEaten)
|
||||
return;
|
||||
|
||||
// Probably isn't needed, but just in case...
|
||||
if (hMutex) WaitForSingleObject(hMutex, 100);
|
||||
if (hMutex)
|
||||
WaitForSingleObject(hMutex, 100);
|
||||
|
||||
//printf( "(Lilypad) EatingWndProc! -> 0x%x\n", proc );
|
||||
|
||||
extraProcs = (ExtraWndProcInfo*) realloc(extraProcs, sizeof(ExtraWndProcInfo)*(numExtraProcs+1));
|
||||
extraProcs = (ExtraWndProcInfo *)realloc(extraProcs, sizeof(ExtraWndProcInfo) * (numExtraProcs + 1));
|
||||
extraProcs[numExtraProcs].proc = proc;
|
||||
extraProcs[numExtraProcs].flags = flags;
|
||||
numExtraProcs++;
|
||||
|
|
|
@ -29,7 +29,8 @@ enum ExtraWndProcResult {
|
|||
|
||||
typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *out);
|
||||
|
||||
struct ExtraWndProcInfo {
|
||||
struct ExtraWndProcInfo
|
||||
{
|
||||
ExtraWndProc proc;
|
||||
DWORD flags;
|
||||
};
|
||||
|
@ -39,7 +40,7 @@ class WndProcEater
|
|||
public:
|
||||
HWND hWndEaten;
|
||||
WNDPROC eatenWndProc;
|
||||
ExtraWndProcInfo* extraProcs;
|
||||
ExtraWndProcInfo *extraProcs;
|
||||
int numExtraProcs;
|
||||
|
||||
HANDLE hMutex;
|
||||
|
|
|
@ -61,9 +61,9 @@ typedef struct
|
|||
|
||||
// This way, I don't require that XInput junk be installed.
|
||||
typedef void(CALLBACK *_XInputEnable)(BOOL enable);
|
||||
typedef DWORD(CALLBACK *_XInputGetStateEx)(DWORD dwUserIndex, XINPUT_STATE* pState);
|
||||
typedef DWORD(CALLBACK *_XInputGetExtended)(DWORD dwUserIndex, SCP_EXTN* pPressure);
|
||||
typedef DWORD(CALLBACK *_XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
|
||||
typedef DWORD(CALLBACK *_XInputGetStateEx)(DWORD dwUserIndex, XINPUT_STATE *pState);
|
||||
typedef DWORD(CALLBACK *_XInputGetExtended)(DWORD dwUserIndex, SCP_EXTN *pPressure);
|
||||
typedef DWORD(CALLBACK *_XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration);
|
||||
|
||||
_XInputEnable pXInputEnable = 0;
|
||||
_XInputGetStateEx pXInputGetStateEx = 0;
|
||||
|
@ -73,32 +73,37 @@ _XInputSetState pXInputSetState = 0;
|
|||
static int xInputActiveCount = 0;
|
||||
|
||||
// Completely unncessary, really.
|
||||
__forceinline int ShortToAxis(int v) {
|
||||
__forceinline int ShortToAxis(int v)
|
||||
{
|
||||
// If positive and at least 1 << 14, increment.
|
||||
v += (!((v>>15)&1)) & ((v>>14)&1);
|
||||
v += (!((v >> 15) & 1)) & ((v >> 14) & 1);
|
||||
// Just double.
|
||||
return v * 2;
|
||||
}
|
||||
|
||||
class XInputDevice : public Device {
|
||||
class XInputDevice : public Device
|
||||
{
|
||||
// Cached last vibration values by pad and motor.
|
||||
// Need this, as only one value is changed at a time.
|
||||
int ps2Vibration[2][4][2];
|
||||
// Minor optimization - cache last set vibration values
|
||||
// When there's no change, no need to do anything.
|
||||
XINPUT_VIBRATION xInputVibration;
|
||||
|
||||
public:
|
||||
int index;
|
||||
|
||||
XInputDevice(int index, wchar_t *displayName) : Device(XINPUT, OTHER, displayName) {
|
||||
XInputDevice(int index, wchar_t *displayName)
|
||||
: Device(XINPUT, OTHER, displayName)
|
||||
{
|
||||
memset(ps2Vibration, 0, sizeof(ps2Vibration));
|
||||
memset(&xInputVibration, 0, sizeof(xInputVibration));
|
||||
this->index = index;
|
||||
int i;
|
||||
for (i=0; i<17; i++) { // Skip empty bit
|
||||
for (i = 0; i < 17; i++) { // Skip empty bit
|
||||
AddPhysicalControl(PRESSURE_BTN, i + (i > 10), 0);
|
||||
}
|
||||
for (; i<21; i++) {
|
||||
for (; i < 21; i++) {
|
||||
AddPhysicalControl(ABSAXIS, i + 2, 0);
|
||||
}
|
||||
AddFFAxis(L"Slow Motor", 0);
|
||||
|
@ -106,7 +111,8 @@ public:
|
|||
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT);
|
||||
}
|
||||
|
||||
wchar_t *GetPhysicalControlName(PhysicalControl *c) {
|
||||
wchar_t *GetPhysicalControlName(PhysicalControl *c)
|
||||
{
|
||||
const static wchar_t *names[] = {
|
||||
L"D-pad Up",
|
||||
L"D-pad Down",
|
||||
|
@ -130,15 +136,17 @@ public:
|
|||
L"Right Thumb X",
|
||||
L"Right Thumb Y",
|
||||
};
|
||||
unsigned int i = (unsigned int) (c - physicalControls);
|
||||
unsigned int i = (unsigned int)(c - physicalControls);
|
||||
if (i < 21) {
|
||||
return (wchar_t*)names[i];
|
||||
return (wchar_t *)names[i];
|
||||
}
|
||||
return Device::GetPhysicalControlName(c);
|
||||
}
|
||||
|
||||
int Activate(InitInfo *initInfo) {
|
||||
if (active) Deactivate();
|
||||
int Activate(InitInfo *initInfo)
|
||||
{
|
||||
if (active)
|
||||
Deactivate();
|
||||
if (!xInputActiveCount) {
|
||||
pXInputEnable(1);
|
||||
}
|
||||
|
@ -148,8 +156,10 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
int Update() {
|
||||
if (!active) return 0;
|
||||
int Update()
|
||||
{
|
||||
if (!active)
|
||||
return 0;
|
||||
XINPUT_STATE state;
|
||||
if (ERROR_SUCCESS != pXInputGetStateEx(index, &state)) {
|
||||
Deactivate();
|
||||
|
@ -193,12 +203,13 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) {
|
||||
void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force)
|
||||
{
|
||||
ps2Vibration[port][slot][motor] = force;
|
||||
int newVibration[2] = {0,0};
|
||||
for (int p=0; p<2; p++) {
|
||||
for (int s=0; s<4; s++) {
|
||||
for (int i=0; i<pads[p][s].numFFBindings; i++) {
|
||||
int newVibration[2] = {0, 0};
|
||||
for (int p = 0; p < 2; p++) {
|
||||
for (int s = 0; s < 4; s++) {
|
||||
for (int i = 0; i < pads[p][s].numFFBindings; i++) {
|
||||
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
|
||||
ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i];
|
||||
newVibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
|
||||
|
@ -222,7 +233,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {
|
||||
void SetEffect(ForceFeedbackBinding *binding, unsigned char force)
|
||||
{
|
||||
PadBindings pBackup = pads[0][0];
|
||||
pads[0][0].ffBindings = binding;
|
||||
pads[0][0].numFFBindings = 1;
|
||||
|
@ -230,7 +242,8 @@ public:
|
|||
pads[0][0] = pBackup;
|
||||
}
|
||||
|
||||
void Deactivate() {
|
||||
void Deactivate()
|
||||
{
|
||||
memset(&xInputVibration, 0, sizeof(xInputVibration));
|
||||
memset(ps2Vibration, 0, sizeof(ps2Vibration));
|
||||
pXInputSetState(index, &xInputVibration);
|
||||
|
@ -244,16 +257,19 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
~XInputDevice() {
|
||||
~XInputDevice()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void EnumXInputDevices() {
|
||||
void EnumXInputDevices()
|
||||
{
|
||||
wchar_t temp[30];
|
||||
if (!pXInputSetState) {
|
||||
// Also used as flag to indicute XInput not installed, so
|
||||
// don't repeatedly try to load it.
|
||||
if (pXInputEnable) return;
|
||||
if (pXInputEnable)
|
||||
return;
|
||||
|
||||
// Prefer XInput 1.3 since SCP only has an XInput 1.3 wrapper right now.
|
||||
// Also use LoadLibrary and not LoadLibraryEx for XInput 1.3, since some
|
||||
|
@ -265,11 +281,11 @@ void EnumXInputDevices() {
|
|||
}
|
||||
|
||||
if (hMod) {
|
||||
if ((pXInputEnable = (_XInputEnable) GetProcAddress(hMod, "XInputEnable")) &&
|
||||
((pXInputGetStateEx = (_XInputGetStateEx) GetProcAddress(hMod, (LPCSTR)100)) || // Try Ex version first
|
||||
(pXInputGetStateEx = (_XInputGetStateEx) GetProcAddress(hMod, "XInputGetState")))) {
|
||||
if ((pXInputEnable = (_XInputEnable)GetProcAddress(hMod, "XInputEnable")) &&
|
||||
((pXInputGetStateEx = (_XInputGetStateEx)GetProcAddress(hMod, (LPCSTR)100)) || // Try Ex version first
|
||||
(pXInputGetStateEx = (_XInputGetStateEx)GetProcAddress(hMod, "XInputGetState")))) {
|
||||
pXInputGetExtended = (_XInputGetExtended)GetProcAddress(hMod, "XInputGetExtended");
|
||||
pXInputSetState = (_XInputSetState) GetProcAddress(hMod, "XInputSetState");
|
||||
pXInputSetState = (_XInputSetState)GetProcAddress(hMod, "XInputSetState");
|
||||
}
|
||||
}
|
||||
if (!pXInputSetState) {
|
||||
|
@ -284,4 +300,3 @@ void EnumXInputDevices() {
|
|||
}
|
||||
pXInputEnable(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -97,20 +97,23 @@
|
|||
|
||||
|
||||
/* All standard descriptors have these 2 fields in common */
|
||||
struct usb_descriptor_header {
|
||||
struct usb_descriptor_header
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
};
|
||||
|
||||
/* String descriptor */
|
||||
struct usb_string_descriptor {
|
||||
struct usb_string_descriptor
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned short wData[1];
|
||||
};
|
||||
|
||||
/* HID descriptor */
|
||||
struct usb_hid_descriptor {
|
||||
struct usb_hid_descriptor
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned short bcdHID;
|
||||
|
@ -120,7 +123,8 @@ struct usb_hid_descriptor {
|
|||
|
||||
/* Endpoint descriptor */
|
||||
#define USB_MAXENDPOINTS 32
|
||||
struct usb_endpoint_descriptor {
|
||||
struct usb_endpoint_descriptor
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bEndpointAddress;
|
||||
|
@ -145,7 +149,8 @@ struct usb_endpoint_descriptor {
|
|||
|
||||
/* Interface descriptor */
|
||||
#define USB_MAXINTERFACES 32
|
||||
struct usb_interface_descriptor {
|
||||
struct usb_interface_descriptor
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bInterfaceNumber;
|
||||
|
@ -164,7 +169,8 @@ struct usb_interface_descriptor {
|
|||
|
||||
#define USB_MAXALTSETTING 128 /* Hard limit */
|
||||
|
||||
struct usb_interface {
|
||||
struct usb_interface
|
||||
{
|
||||
struct usb_interface_descriptor *altsetting;
|
||||
|
||||
int num_altsetting;
|
||||
|
@ -172,7 +178,8 @@ struct usb_interface {
|
|||
|
||||
/* Configuration descriptor information.. */
|
||||
#define USB_MAXCONFIG 8
|
||||
struct usb_config_descriptor {
|
||||
struct usb_config_descriptor
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned short wTotalLength;
|
||||
|
@ -189,7 +196,8 @@ struct usb_config_descriptor {
|
|||
};
|
||||
|
||||
/* Device descriptor */
|
||||
struct usb_device_descriptor {
|
||||
struct usb_device_descriptor
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned short bcdUSB;
|
||||
|
@ -206,7 +214,8 @@ struct usb_device_descriptor {
|
|||
unsigned char bNumConfigurations;
|
||||
};
|
||||
|
||||
struct usb_ctrl_setup {
|
||||
struct usb_ctrl_setup
|
||||
{
|
||||
unsigned char bRequestType;
|
||||
unsigned char bRequest;
|
||||
unsigned short wValue;
|
||||
|
@ -261,7 +270,8 @@ struct usb_ctrl_setup {
|
|||
/* struct usb_device; */
|
||||
/* struct usb_bus; */
|
||||
|
||||
struct usb_device {
|
||||
struct usb_device
|
||||
{
|
||||
struct usb_device *next, *prev;
|
||||
|
||||
char filename[LIBUSB_PATH_MAX];
|
||||
|
@ -279,7 +289,8 @@ struct usb_device {
|
|||
struct usb_device **children;
|
||||
};
|
||||
|
||||
struct usb_bus {
|
||||
struct usb_bus
|
||||
{
|
||||
struct usb_bus *next, *prev;
|
||||
|
||||
char dirname[LIBUSB_PATH_MAX];
|
||||
|
@ -291,14 +302,17 @@ struct usb_bus {
|
|||
};
|
||||
|
||||
/* Version information, Windows specific */
|
||||
struct usb_version {
|
||||
struct {
|
||||
struct usb_version
|
||||
{
|
||||
struct
|
||||
{
|
||||
int major;
|
||||
int minor;
|
||||
int micro;
|
||||
int nano;
|
||||
} dll;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
int major;
|
||||
int minor;
|
||||
int micro;
|
||||
|
@ -324,92 +338,92 @@ typedef struct usb_dev_handle usb_dev_handle;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Function prototypes */
|
||||
/* Function prototypes */
|
||||
|
||||
/* usb.c */
|
||||
usb_dev_handle *usb_open(struct usb_device *dev);
|
||||
int usb_close(usb_dev_handle *dev);
|
||||
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
|
||||
/* usb.c */
|
||||
usb_dev_handle *usb_open(struct usb_device *dev);
|
||||
int usb_close(usb_dev_handle *dev);
|
||||
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
|
||||
size_t buflen);
|
||||
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf,
|
||||
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf,
|
||||
size_t buflen);
|
||||
|
||||
/* descriptors.c */
|
||||
int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
|
||||
/* descriptors.c */
|
||||
int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
|
||||
unsigned char type, unsigned char index,
|
||||
void *buf, int size);
|
||||
int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
|
||||
int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
|
||||
unsigned char index, void *buf, int size);
|
||||
|
||||
/* <arch>.c */
|
||||
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
|
||||
/* <arch>.c */
|
||||
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
|
||||
int timeout);
|
||||
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
|
||||
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
|
||||
int timeout);
|
||||
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
|
||||
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
|
||||
int timeout);
|
||||
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
|
||||
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
|
||||
int timeout);
|
||||
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
|
||||
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
|
||||
int value, int index, char *bytes, int size,
|
||||
int timeout);
|
||||
int usb_set_configuration(usb_dev_handle *dev, int configuration);
|
||||
int usb_claim_interface(usb_dev_handle *dev, int interface);
|
||||
int usb_release_interface(usb_dev_handle *dev, int interface);
|
||||
int usb_set_altinterface(usb_dev_handle *dev, int alternate);
|
||||
int usb_resetep(usb_dev_handle *dev, unsigned int ep);
|
||||
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);
|
||||
int usb_reset(usb_dev_handle *dev);
|
||||
int usb_set_configuration(usb_dev_handle *dev, int configuration);
|
||||
int usb_claim_interface(usb_dev_handle *dev, int interface);
|
||||
int usb_release_interface(usb_dev_handle *dev, int interface);
|
||||
int usb_set_altinterface(usb_dev_handle *dev, int alternate);
|
||||
int usb_resetep(usb_dev_handle *dev, unsigned int ep);
|
||||
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);
|
||||
int usb_reset(usb_dev_handle *dev);
|
||||
|
||||
char *usb_strerror(void);
|
||||
char *usb_strerror(void);
|
||||
|
||||
void usb_init(void);
|
||||
void usb_set_debug(int level);
|
||||
int usb_find_busses(void);
|
||||
int usb_find_devices(void);
|
||||
struct usb_device *usb_device(usb_dev_handle *dev);
|
||||
struct usb_bus *usb_get_busses(void);
|
||||
void usb_init(void);
|
||||
void usb_set_debug(int level);
|
||||
int usb_find_busses(void);
|
||||
int usb_find_devices(void);
|
||||
struct usb_device *usb_device(usb_dev_handle *dev);
|
||||
struct usb_bus *usb_get_busses(void);
|
||||
|
||||
|
||||
/* Windows specific functions */
|
||||
/* Windows specific functions */
|
||||
|
||||
#define LIBUSB_HAS_INSTALL_SERVICE_NP 1
|
||||
int usb_install_service_np(void);
|
||||
void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance,
|
||||
#define LIBUSB_HAS_INSTALL_SERVICE_NP 1
|
||||
int usb_install_service_np(void);
|
||||
void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance,
|
||||
LPSTR cmd_line, int cmd_show);
|
||||
|
||||
#define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1
|
||||
int usb_uninstall_service_np(void);
|
||||
void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance,
|
||||
#define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1
|
||||
int usb_uninstall_service_np(void);
|
||||
void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance,
|
||||
LPSTR cmd_line, int cmd_show);
|
||||
|
||||
#define LIBUSB_HAS_INSTALL_DRIVER_NP 1
|
||||
int usb_install_driver_np(const char *inf_file);
|
||||
void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance,
|
||||
#define LIBUSB_HAS_INSTALL_DRIVER_NP 1
|
||||
int usb_install_driver_np(const char *inf_file);
|
||||
void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance,
|
||||
LPSTR cmd_line, int cmd_show);
|
||||
|
||||
#define LIBUSB_HAS_TOUCH_INF_FILE_NP 1
|
||||
int usb_touch_inf_file_np(const char *inf_file);
|
||||
void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance,
|
||||
#define LIBUSB_HAS_TOUCH_INF_FILE_NP 1
|
||||
int usb_touch_inf_file_np(const char *inf_file);
|
||||
void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance,
|
||||
LPSTR cmd_line, int cmd_show);
|
||||
|
||||
#define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1
|
||||
int usb_install_needs_restart_np(void);
|
||||
#define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1
|
||||
int usb_install_needs_restart_np(void);
|
||||
|
||||
const struct usb_version *usb_get_version(void);
|
||||
const struct usb_version *usb_get_version(void);
|
||||
|
||||
int usb_isochronous_setup_async(usb_dev_handle *dev, void **context,
|
||||
int usb_isochronous_setup_async(usb_dev_handle *dev, void **context,
|
||||
unsigned char ep, int pktsize);
|
||||
int usb_bulk_setup_async(usb_dev_handle *dev, void **context,
|
||||
int usb_bulk_setup_async(usb_dev_handle *dev, void **context,
|
||||
unsigned char ep);
|
||||
int usb_interrupt_setup_async(usb_dev_handle *dev, void **context,
|
||||
int usb_interrupt_setup_async(usb_dev_handle *dev, void **context,
|
||||
unsigned char ep);
|
||||
|
||||
int usb_submit_async(void *context, char *bytes, int size);
|
||||
int usb_reap_async(void *context, int timeout);
|
||||
int usb_reap_async_nocancel(void *context, int timeout);
|
||||
int usb_cancel_async(void *context);
|
||||
int usb_free_async(void **context);
|
||||
int usb_submit_async(void *context, char *bytes, int size);
|
||||
int usb_reap_async(void *context, int timeout);
|
||||
int usb_reap_async_nocancel(void *context, int timeout);
|
||||
int usb_cancel_async(void *context);
|
||||
int usb_free_async(void **context);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -418,4 +432,3 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#endif /* __USB_H__ */
|
||||
|
||||
|
|
Loading…
Reference in New Issue