PAD: windows: clang-format

This commit is contained in:
Gauvain 'GovanifY' Roussel-Tarbouriech 2020-12-12 09:51:22 +01:00 committed by lightningterror
parent 9cdc963c97
commit 8067a480c7
31 changed files with 7710 additions and 6618 deletions

View File

@ -34,23 +34,23 @@
void EnumDevices(int hideDXXinput) void EnumDevices(int hideDXXinput)
{ {
// Needed for enumeration of some device types. // Needed for enumeration of some device types.
dm->ReleaseInput(); dm->ReleaseInput();
InputDeviceManager *oldDm = dm; InputDeviceManager* oldDm = dm;
dm = new InputDeviceManager(); dm = new InputDeviceManager();
#ifdef _MSC_VER #ifdef _MSC_VER
EnumWindowsMessagingDevices(); EnumWindowsMessagingDevices();
EnumRawInputDevices(); EnumRawInputDevices();
EnumDualShock3s(); EnumDualShock3s();
EnumXInputDevices(); EnumXInputDevices();
EnumDirectInputDevices(hideDXXinput); EnumDirectInputDevices(hideDXXinput);
#else #else
EnumLnx(); EnumLnx();
EnumJoystickEvdev(); EnumJoystickEvdev();
#endif #endif
dm->CopyBindings(oldDm->numDevices, oldDm->devices); dm->CopyBindings(oldDm->numDevices, oldDm->devices);
delete oldDm; delete oldDm;
} }

View File

@ -22,123 +22,142 @@
#include "InputManager.h" #include "InputManager.h"
#include "WndProcEater.h" #include "WndProcEater.h"
Device *dev; 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; int i;
HWND hWndList = GetDlgItem(hWnd, IDC_DIAG_LIST); HWND hWndList = GetDlgItem(hWnd, IDC_DIAG_LIST);
static int fullRefresh; static int fullRefresh;
if (dev) { if (dev)
switch (uMsg) { {
case WM_INITDIALOG: { switch (uMsg)
fullRefresh = 1; {
SetWindowText(hWnd, dev->displayName); case WM_INITDIALOG:
LVCOLUMNW c; {
c.mask = LVCF_TEXT | LVCF_WIDTH; fullRefresh = 1;
c.cx = 151; SetWindowText(hWnd, dev->displayName);
c.pszText = L"Control"; LVCOLUMNW c;
ListView_InsertColumn(hWndList, 0, &c); c.mask = LVCF_TEXT | LVCF_WIDTH;
c.cx = 90; c.cx = 151;
c.pszText = L"Value"; c.pszText = L"Control";
ListView_InsertColumn(hWndList, 1, &c); ListView_InsertColumn(hWndList, 0, &c);
ListView_DeleteAllItems(hWndList); c.cx = 90;
LVITEM item; c.pszText = L"Value";
item.mask = LVIF_TEXT; ListView_InsertColumn(hWndList, 1, &c);
item.iSubItem = 0; ListView_DeleteAllItems(hWndList);
for (i = 0; i < dev->numVirtualControls; i++) { LVITEM item;
item.pszText = dev->GetVirtualControlName(dev->virtualControls + i); item.mask = LVIF_TEXT;
item.iItem = i; item.iSubItem = 0;
ListView_InsertItem(hWndList, &item); for (i = 0; i < dev->numVirtualControls; i++)
} {
SetTimer(hWnd, 1, 200, 0); item.pszText = dev->GetVirtualControlName(dev->virtualControls + i);
} item.iItem = i;
//break; ListView_InsertItem(hWndList, &item);
case WM_TIMER: { }
hWndButtonProc.SetWndHandle(hWndList); SetTimer(hWnd, 1, 200, 0);
InitInfo info = {0, 1, hWnd, &hWndButtonProc}; }
dm->Update(&info); //break;
LVITEMW item; case WM_TIMER:
item.mask = LVIF_TEXT; {
item.iSubItem = 1; hWndButtonProc.SetWndHandle(hWndList);
//ShowWindow(hWndList, 0); InitInfo info = {0, 1, hWnd, &hWndButtonProc};
//LockWindowUpdate(hWndList); dm->Update(&info);
if (!dev->active) { LVITEMW item;
item.pszText = L"N/A"; item.mask = LVIF_TEXT;
for (i = 0; i < dev->numVirtualControls; i++) { item.iSubItem = 1;
item.iItem = i; //ShowWindow(hWndList, 0);
ListView_SetItem(hWndList, &item); //LockWindowUpdate(hWndList);
} if (!dev->active)
fullRefresh = 1; {
} else { item.pszText = L"N/A";
for (i = 0; i < dev->numVirtualControls; i++) { for (i = 0; i < dev->numVirtualControls; i++)
if (fullRefresh || dev->virtualControlState[i] != dev->oldVirtualControlState[i]) { {
item.iItem = i;
ListView_SetItem(hWndList, &item);
}
fullRefresh = 1;
}
else
{
for (i = 0; i < dev->numVirtualControls; i++)
{
if (fullRefresh || dev->virtualControlState[i] != dev->oldVirtualControlState[i])
{
VirtualControl *c = dev->virtualControls + i; VirtualControl* c = dev->virtualControls + i;
wchar_t temp[50]; wchar_t temp[50];
int val = dev->virtualControlState[i]; int val = dev->virtualControlState[i];
if (c->uid & (UID_POV)) { if (c->uid & (UID_POV))
wsprintfW(temp, L"%i", val); {
} else { wsprintfW(temp, L"%i", val);
wchar_t *sign = L""; }
if (val < 0) { else
sign = L"-"; {
val = -val; wchar_t* sign = L"";
} if (val < 0)
if ((c->uid & UID_AXIS) && val) { {
val = val; sign = L"-";
} val = -val;
val = (int)floor(0.5 + val * 1000.0 / (double)FULLY_DOWN); }
wsprintfW(temp, L"%s%i.%03i", sign, val / 1000, val % 1000); if ((c->uid & UID_AXIS) && val)
} {
item.pszText = temp; val = val;
item.iItem = i; }
ListView_SetItem(hWndList, &item); val = (int)floor(0.5 + val * 1000.0 / (double)FULLY_DOWN);
} wsprintfW(temp, L"%s%i.%03i", sign, val / 1000, val % 1000);
} }
dm->PostRead(); item.pszText = temp;
fullRefresh = 0; item.iItem = i;
} ListView_SetItem(hWndList, &item);
//LockWindowUpdate(0); }
//ShowWindow(hWndList, 1); }
//UpdateWindow(hWnd); dm->PostRead();
} break; fullRefresh = 0;
case WM_NOTIFY: { }
NMLVKEYDOWN *n = (NMLVKEYDOWN *)lParam; //LockWindowUpdate(0);
// Don't always get the notification when testing DirectInput non-keyboard devices. //ShowWindow(hWndList, 1);
// Don't get it (Or want it) when testing keyboards. //UpdateWindow(hWnd);
if (n->hdr.idFrom != IDC_DIAG_LIST || n->hdr.code != LVN_KEYDOWN || n->wVKey != VK_ESCAPE) }
break; break;
} case WM_NOTIFY:
case WM_ACTIVATE: {
if (uMsg == WM_ACTIVATE && wParam != WA_INACTIVE) NMLVKEYDOWN* n = (NMLVKEYDOWN*)lParam;
break; // Don't always get the notification when testing DirectInput non-keyboard devices.
break; // Don't get it (Or want it) when testing keyboards.
case WM_CLOSE: if (n->hdr.idFrom != IDC_DIAG_LIST || n->hdr.code != LVN_KEYDOWN || n->wVKey != VK_ESCAPE)
KillTimer(hWnd, 1); break;
dm->ReleaseInput(); }
// Prevents reaching this branch again. case WM_ACTIVATE:
dev = 0; if (uMsg == WM_ACTIVATE && wParam != WA_INACTIVE)
EndDialog(hWnd, 1); break;
break; break;
default: case WM_CLOSE:
break; KillTimer(hWnd, 1);
} dm->ReleaseInput();
} // Prevents reaching this branch again.
return 0; dev = 0;
EndDialog(hWnd, 1);
break;
default:
break;
}
}
return 0;
} }
void Diagnose(int id, HWND hWnd) void Diagnose(int id, HWND hWnd)
{ {
// init = 0; // init = 0;
dev = dm->devices[id]; dev = dm->devices[id];
for (int i = 0; i < dm->numDevices; i++) { for (int i = 0; i < dm->numDevices; i++)
if (i != id) {
dm->DisableDevice(i); if (i != id)
// Shouldn't be needed. dm->DisableDevice(i);
else // Shouldn't be needed.
dm->EnableDevice(i); else
} dm->EnableDevice(i);
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIAG), hWnd, DiagDialog); }
ClearKeyQueue(); DialogBox(hInst, MAKEINTRESOURCE(IDD_DIAG), hWnd, DiagDialog);
ClearKeyQueue();
} }

File diff suppressed because it is too large Load Diff

View File

@ -41,15 +41,15 @@
unsigned int lastDS3Check = 0; unsigned int lastDS3Check = 0;
unsigned int lastDS3Enum = 0; unsigned int lastDS3Enum = 0;
typedef void(__cdecl *_usb_init)(void); typedef void(__cdecl* _usb_init)(void);
typedef int(__cdecl *_usb_close)(usb_dev_handle *dev); 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 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 usb_dev_handle*(__cdecl* _usb_open)(struct usb_device* dev);
typedef int(__cdecl *_usb_find_busses)(void); typedef int(__cdecl* _usb_find_busses)(void);
typedef int(__cdecl *_usb_find_devices)(void); typedef int(__cdecl* _usb_find_devices)(void);
typedef struct usb_bus *(__cdecl *_usb_get_busses)(void); typedef struct usb_bus*(__cdecl* _usb_get_busses)(void);
typedef usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev); 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_init pusb_init;
_usb_close pusb_close; _usb_close pusb_close;
@ -64,434 +64,477 @@ HMODULE hModLibusb = 0;
void UninitLibUsb() void UninitLibUsb()
{ {
if (hModLibusb) { if (hModLibusb)
FreeLibrary(hModLibusb); {
hModLibusb = 0; FreeLibrary(hModLibusb);
} hModLibusb = 0;
}
} }
void TryInitDS3(usb_device *dev) void TryInitDS3(usb_device* dev)
{ {
while (dev) { while (dev)
if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID) { {
usb_dev_handle *handle = pusb_open(dev); if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID)
if (handle) { {
char junk[20]; usb_dev_handle* handle = pusb_open(dev);
// This looks like HidD_GetFeature with a feature report id of 0xF2 to me and a length of 17. if (handle)
// That doesn't work, however, and 17 is shorter than the report length. {
pusb_control_msg(handle, 0xa1, 1, 0x03f2, dev->config->interface->altsetting->bInterfaceNumber, junk, 17, 1000); char junk[20];
pusb_close(handle); // This looks like HidD_GetFeature with a feature report id of 0xF2 to me and a length of 17.
} // That doesn't work, however, and 17 is shorter than the report length.
} pusb_control_msg(handle, 0xa1, 1, 0x03f2, dev->config->interface->altsetting->bInterfaceNumber, junk, 17, 1000);
if (dev->num_children) { pusb_close(handle);
for (int i = 0; i < dev->num_children; i++) { }
TryInitDS3(dev->children[i]); }
} if (dev->num_children)
} {
dev = dev->next; for (int i = 0; i < dev->num_children; i++)
} {
TryInitDS3(dev->children[i]);
}
}
dev = dev->next;
}
} }
void DS3Enum(unsigned int time) void DS3Enum(unsigned int time)
{ {
if (time - lastDS3Enum < DOUBLE_ENUM_DELAY) { if (time - lastDS3Enum < DOUBLE_ENUM_DELAY)
return; {
} return;
lastDS3Enum = time; }
pusb_find_busses(); lastDS3Enum = time;
pusb_find_devices(); pusb_find_busses();
pusb_find_devices();
} }
void DS3Check(unsigned int time) void DS3Check(unsigned int time)
{ {
if (time - lastDS3Check < DOUBLE_CHECK_DELAY) { if (time - lastDS3Check < DOUBLE_CHECK_DELAY)
return; {
} return;
if (!lastDS3Check) { }
DS3Enum(time); if (!lastDS3Check)
} {
lastDS3Check = time; DS3Enum(time);
}
lastDS3Check = time;
usb_bus *bus = pusb_get_busses(); usb_bus* bus = pusb_get_busses();
while (bus) { while (bus)
TryInitDS3(bus->devices); {
bus = bus->next; TryInitDS3(bus->devices);
} bus = bus->next;
}
} }
int InitLibUsb() int InitLibUsb()
{ {
if (hModLibusb) { if (hModLibusb)
return 1; {
} return 1;
hModLibusb = LoadLibraryA("C:\\windows\\system32\\libusb0.dll"); }
if (hModLibusb) { hModLibusb = LoadLibraryA("C:\\windows\\system32\\libusb0.dll");
if ((pusb_init = (_usb_init)GetProcAddress(hModLibusb, "usb_init")) && if (hModLibusb)
(pusb_close = (_usb_close)GetProcAddress(hModLibusb, "usb_close")) && {
(pusb_get_string_simple = (_usb_get_string_simple)GetProcAddress(hModLibusb, "usb_get_string_simple")) && if ((pusb_init = (_usb_init)GetProcAddress(hModLibusb, "usb_init")) &&
(pusb_open = (_usb_open)GetProcAddress(hModLibusb, "usb_open")) && (pusb_close = (_usb_close)GetProcAddress(hModLibusb, "usb_close")) &&
(pusb_find_busses = (_usb_find_busses)GetProcAddress(hModLibusb, "usb_find_busses")) && (pusb_get_string_simple = (_usb_get_string_simple)GetProcAddress(hModLibusb, "usb_get_string_simple")) &&
(pusb_find_devices = (_usb_find_devices)GetProcAddress(hModLibusb, "usb_find_devices")) && (pusb_open = (_usb_open)GetProcAddress(hModLibusb, "usb_open")) &&
(pusb_get_busses = (_usb_get_busses)GetProcAddress(hModLibusb, "usb_get_busses")) && (pusb_find_busses = (_usb_find_busses)GetProcAddress(hModLibusb, "usb_find_busses")) &&
(pusb_control_msg = (_usb_control_msg)GetProcAddress(hModLibusb, "usb_control_msg"))) { (pusb_find_devices = (_usb_find_devices)GetProcAddress(hModLibusb, "usb_find_devices")) &&
pusb_init(); (pusb_get_busses = (_usb_get_busses)GetProcAddress(hModLibusb, "usb_get_busses")) &&
return 1; (pusb_control_msg = (_usb_control_msg)GetProcAddress(hModLibusb, "usb_control_msg")))
} {
UninitLibUsb(); pusb_init();
} return 1;
return 0; }
UninitLibUsb();
}
return 0;
} }
int DualShock3Possible() int DualShock3Possible()
{ {
return InitLibUsb(); return InitLibUsb();
} }
#include <pshpack1.h> #include <pshpack1.h>
struct MotorState struct MotorState
{ {
unsigned char duration; unsigned char duration;
unsigned char force; unsigned char force;
}; };
struct LightState struct LightState
{ {
// 0xFF makes it stay on. // 0xFF makes it stay on.
unsigned char duration; unsigned char duration;
// Have to make one or the other non-zero to turn on light. // Have to make one or the other non-zero to turn on light.
unsigned char dunno[2]; unsigned char dunno[2];
// 0 is fully lit. // 0 is fully lit.
unsigned char dimness; unsigned char dimness;
// Have to make non-zero to turn on light. // Have to make non-zero to turn on light.
unsigned char on; unsigned char on;
}; };
// Data sent to DS3 to set state. // Data sent to DS3 to set state.
struct DS3Command struct DS3Command
{ {
unsigned char id; unsigned char id;
unsigned char unsure; unsigned char unsure;
// Small is first, then big. // Small is first, then big.
MotorState motors[2]; MotorState motors[2];
unsigned char noClue[4]; unsigned char noClue[4];
// 2 is pad 1 light, 4 is pad 2, 8 is pad 3, 16 is pad 4. No clue about the others. // 2 is pad 1 light, 4 is pad 2, 8 is pad 3, 16 is pad 4. No clue about the others.
unsigned char lightFlags; unsigned char lightFlags;
// Lights are in reverse order. pad 1 is last. // Lights are in reverse order. pad 1 is last.
LightState lights[4]; LightState lights[4];
unsigned char dunno[18]; unsigned char dunno[18];
}; };
#include <poppack.h> #include <poppack.h>
int CharToAxis(unsigned char c) int CharToAxis(unsigned char c)
{ {
int v = (int)c + ((unsigned int)c >> 7); 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); 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. // Cached last vibration values by pad and motor.
// Need this, as only one value is changed at a time. // Need this, as only one value is changed at a time.
int ps2Vibration[2][4][2]; int ps2Vibration[2][4][2];
int vibration[2]; int vibration[2];
public: public:
int index; int index;
HANDLE hFile; HANDLE hFile;
DS3Command sendState; DS3Command sendState;
unsigned char getState[49]; unsigned char getState[49];
OVERLAPPED readop; OVERLAPPED readop;
OVERLAPPED writeop; OVERLAPPED writeop;
int writeCount; int writeCount;
int lastWrite; int lastWrite;
unsigned int dataLastReceived; unsigned int dataLastReceived;
int writeQueued; int writeQueued;
int writing; int writing;
int StartRead() int StartRead()
{ {
int res = ReadFile(hFile, &getState, sizeof(getState), 0, &readop); int res = ReadFile(hFile, &getState, sizeof(getState), 0, &readop);
return (res || GetLastError() == ERROR_IO_PENDING); return (res || GetLastError() == ERROR_IO_PENDING);
} }
void QueueWrite() void QueueWrite()
{ {
// max of 2 queued writes allowed, one for either motor. // max of 2 queued writes allowed, one for either motor.
if (writeQueued < 2) { if (writeQueued < 2)
writeQueued++; {
StartWrite(); writeQueued++;
} StartWrite();
} }
}
int StartWrite() int StartWrite()
{ {
if (!writing && writeQueued) { if (!writing && writeQueued)
lastWrite = GetTickCount(); {
writing++; lastWrite = GetTickCount();
writeQueued--; writing++;
sendState.motors[0].duration = 0x50; writeQueued--;
sendState.motors[1].duration = 0x50; sendState.motors[0].duration = 0x50;
sendState.motors[1].duration = 0x50;
int bigForce = vibration[0] * 256 / FULLY_DOWN; int bigForce = vibration[0] * 256 / FULLY_DOWN;
if (bigForce > 255) if (bigForce > 255)
bigForce = 255; bigForce = 255;
sendState.motors[1].force = (unsigned char)bigForce; sendState.motors[1].force = (unsigned char)bigForce;
sendState.motors[0].force = (unsigned char)(vibration[1] >= FULLY_DOWN / 2); sendState.motors[0].force = (unsigned char)(vibration[1] >= FULLY_DOWN / 2);
// Can't seem to have them both non-zero at once. // Can't seem to have them both non-zero at once.
if (sendState.motors[writeCount & 1].force) { if (sendState.motors[writeCount & 1].force)
sendState.motors[(writeCount & 1) ^ 1].force = 0; {
sendState.motors[(writeCount & 1) ^ 1].duration = 0; sendState.motors[(writeCount & 1) ^ 1].force = 0;
} sendState.motors[(writeCount & 1) ^ 1].duration = 0;
}
writeCount++; writeCount++;
int res = WriteFile(hFile, &sendState, sizeof(sendState), 0, &writeop); int res = WriteFile(hFile, &sendState, sizeof(sendState), 0, &writeop);
return (res || GetLastError() == ERROR_IO_PENDING); return (res || GetLastError() == ERROR_IO_PENDING);
} }
return 1; return 1;
} }
DualShock3Device(int index, wchar_t *name, wchar_t *path) DualShock3Device(int index, wchar_t* name, wchar_t* path)
: Device(DS3, OTHER, name, path, L"DualShock 3") : Device(DS3, OTHER, name, path, L"DualShock 3")
{ {
writeCount = 0; writeCount = 0;
writing = 0; writing = 0;
writeQueued = 0; writeQueued = 0;
memset(&readop, 0, sizeof(readop)); memset(&readop, 0, sizeof(readop));
memset(&writeop, 0, sizeof(writeop)); memset(&writeop, 0, sizeof(writeop));
memset(&sendState, 0, sizeof(sendState)); memset(&sendState, 0, sizeof(sendState));
sendState.id = 1; sendState.id = 1;
int temp = (index & 4); int temp = (index & 4);
sendState.lightFlags = (1 << (temp + 1)); sendState.lightFlags = (1 << (temp + 1));
sendState.lights[3 - temp].duration = 0xFF; sendState.lights[3 - temp].duration = 0xFF;
sendState.lights[3 - temp].dunno[0] = 1; sendState.lights[3 - temp].dunno[0] = 1;
sendState.lights[3 - temp].on = 1; sendState.lights[3 - temp].on = 1;
memset(ps2Vibration, 0, sizeof(ps2Vibration)); memset(ps2Vibration, 0, sizeof(ps2Vibration));
vibration[0] = vibration[1] = 0; vibration[0] = vibration[1] = 0;
this->index = index; this->index = index;
int i; 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); if (i != 14 && i != 15 && i != 8 && i != 9)
} else { {
AddPhysicalControl(PSHBTN, i, 0); AddPhysicalControl(PRESSURE_BTN, i, 0);
} }
} else
for (; i < 23; i++) { {
AddPhysicalControl(ABSAXIS, i, 0); AddPhysicalControl(PSHBTN, i, 0);
} }
AddFFAxis(L"Big Motor", 0); }
AddFFAxis(L"Small Motor", 1); for (; i < 23; i++)
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT); {
hFile = INVALID_HANDLE_VALUE; AddPhysicalControl(ABSAXIS, i, 0);
} }
AddFFAxis(L"Big Motor", 0);
AddFFAxis(L"Small Motor", 1);
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT);
hFile = INVALID_HANDLE_VALUE;
}
wchar_t *GetPhysicalControlName(PhysicalControl *c) wchar_t* GetPhysicalControlName(PhysicalControl* c)
{ {
const static wchar_t *names[] = { const static wchar_t* names[] = {
L"Square", L"Square",
L"Cross", L"Cross",
L"Circle", L"Circle",
L"Triangle", L"Triangle",
L"R1", L"R1",
L"L1", L"L1",
L"R2", L"R2",
L"L2", L"L2",
L"R3", L"R3",
L"L3", L"L3",
L"Left", L"Left",
L"Down", L"Down",
L"Right", L"Right",
L"Up", L"Up",
L"Start", L"Start",
L"Select", L"Select",
L"L-Stick X", L"L-Stick X",
L"L-Stick Y", L"L-Stick Y",
L"R-Stick X", L"R-Stick X",
L"R-Stick Y", L"R-Stick Y",
L"Left/Right Tilt", L"Left/Right Tilt",
L"Forward/Back Tilt", L"Forward/Back Tilt",
L"???", L"???",
}; };
unsigned int i = (unsigned int)(c - physicalControls); unsigned int i = (unsigned int)(c - physicalControls);
if (i < sizeof(names) / sizeof(names[0])) { if (i < sizeof(names) / sizeof(names[0]))
return (wchar_t *)names[i]; {
} return (wchar_t*)names[i];
return Device::GetPhysicalControlName(c); }
} return Device::GetPhysicalControlName(c);
}
int Activate(InitInfo *initInfo) int Activate(InitInfo* initInfo)
{ {
if (active) if (active)
Deactivate(); Deactivate();
// Give grace period before get mad. // Give grace period before get mad.
lastWrite = dataLastReceived = GetTickCount(); lastWrite = dataLastReceived = GetTickCount();
readop.hEvent = CreateEvent(0, 0, 0, 0); readop.hEvent = CreateEvent(0, 0, 0, 0);
writeop.hEvent = CreateEvent(0, 0, 0, 0); writeop.hEvent = CreateEvent(0, 0, 0, 0);
hFile = CreateFileW(instanceID, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); hFile = CreateFileW(instanceID, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (!readop.hEvent || !writeop.hEvent || hFile == INVALID_HANDLE_VALUE || if (!readop.hEvent || !writeop.hEvent || hFile == INVALID_HANDLE_VALUE ||
!StartRead()) { !StartRead())
Deactivate(); {
return 0; Deactivate();
} return 0;
active = 1; }
AllocState(); active = 1;
return 1; AllocState();
} return 1;
}
int Update() int Update()
{ {
if (!active) if (!active)
return 0; return 0;
HANDLE h[2] = { HANDLE h[2] = {
readop.hEvent, readop.hEvent,
writeop.hEvent}; writeop.hEvent};
unsigned int time = GetTickCount(); unsigned int time = GetTickCount();
if (time - lastWrite > UPDATE_INTERVAL) { if (time - lastWrite > UPDATE_INTERVAL)
QueueWrite(); {
} QueueWrite();
while (1) { }
DWORD res = WaitForMultipleObjects(2, h, 0, 0); while (1)
if (res == WAIT_OBJECT_0) { {
dataLastReceived = time; DWORD res = WaitForMultipleObjects(2, h, 0, 0);
if (!StartRead()) { if (res == WAIT_OBJECT_0)
Deactivate(); {
return 0; dataLastReceived = time;
} if (!StartRead())
{
Deactivate();
return 0;
}
physicalControlState[0] = CharToButton(getState[25]); physicalControlState[0] = CharToButton(getState[25]);
physicalControlState[1] = CharToButton(getState[24]); physicalControlState[1] = CharToButton(getState[24]);
physicalControlState[2] = CharToButton(getState[23]); physicalControlState[2] = CharToButton(getState[23]);
physicalControlState[3] = CharToButton(getState[22]); physicalControlState[3] = CharToButton(getState[22]);
physicalControlState[4] = CharToButton(getState[21]); physicalControlState[4] = CharToButton(getState[21]);
physicalControlState[5] = CharToButton(getState[20]); physicalControlState[5] = CharToButton(getState[20]);
physicalControlState[6] = CharToButton(getState[19]); physicalControlState[6] = CharToButton(getState[19]);
physicalControlState[7] = CharToButton(getState[18]); physicalControlState[7] = CharToButton(getState[18]);
physicalControlState[10] = CharToButton(getState[17]); physicalControlState[10] = CharToButton(getState[17]);
physicalControlState[11] = CharToButton(getState[16]); physicalControlState[11] = CharToButton(getState[16]);
physicalControlState[12] = CharToButton(getState[15]); physicalControlState[12] = CharToButton(getState[15]);
physicalControlState[13] = CharToButton(getState[14]); physicalControlState[13] = CharToButton(getState[14]);
physicalControlState[8] = ((getState[2] & 4) / 4) * FULLY_DOWN; physicalControlState[8] = ((getState[2] & 4) / 4) * FULLY_DOWN;
physicalControlState[9] = ((getState[2] & 2) / 2) * FULLY_DOWN; physicalControlState[9] = ((getState[2] & 2) / 2) * FULLY_DOWN;
physicalControlState[15] = ((getState[2] & 1) / 1) * FULLY_DOWN; physicalControlState[15] = ((getState[2] & 1) / 1) * FULLY_DOWN;
physicalControlState[14] = ((getState[2] & 8) / 8) * FULLY_DOWN; physicalControlState[14] = ((getState[2] & 8) / 8) * FULLY_DOWN;
physicalControlState[16] = CharToAxis(getState[6]); physicalControlState[16] = CharToAxis(getState[6]);
physicalControlState[17] = CharToAxis(getState[7]); physicalControlState[17] = CharToAxis(getState[7]);
physicalControlState[18] = CharToAxis(getState[8]); physicalControlState[18] = CharToAxis(getState[8]);
physicalControlState[19] = CharToAxis(getState[9]); physicalControlState[19] = CharToAxis(getState[9]);
physicalControlState[20] = CharToAxis(getState[42] + 128); physicalControlState[20] = CharToAxis(getState[42] + 128);
physicalControlState[21] = CharToAxis(getState[44] + 128); physicalControlState[21] = CharToAxis(getState[44] + 128);
physicalControlState[22] = CharToAxis(getState[46] + 128); physicalControlState[22] = CharToAxis(getState[46] + 128);
continue; continue;
} else if (res == WAIT_OBJECT_0 + 1) { }
writing = 0; else if (res == WAIT_OBJECT_0 + 1)
if (!writeQueued && (vibration[0] | vibration[1])) { {
QueueWrite(); writing = 0;
} if (!writeQueued && (vibration[0] | vibration[1]))
if (!StartWrite()) { {
Deactivate(); QueueWrite();
return 0; }
} if (!StartWrite())
} else { {
if (time - dataLastReceived >= DEVICE_CHECK_DELAY) { Deactivate();
if (time - dataLastReceived >= DEVICE_ENUM_DELAY) { return 0;
DS3Enum(time); }
} }
DS3Check(time); else
QueueWrite(); {
} if (time - dataLastReceived >= DEVICE_CHECK_DELAY)
} {
break; if (time - dataLastReceived >= DEVICE_ENUM_DELAY)
} {
return 1; DS3Enum(time);
} }
DS3Check(time);
QueueWrite();
}
}
break;
}
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; ps2Vibration[port][slot][motor] = force;
vibration[0] = vibration[1] = 0; vibration[0] = vibration[1] = 0;
for (int p = 0; p < 2; p++) { for (int p = 0; p < 2; p++)
for (int s = 0; s < 4; s++) { {
int padtype = config.padConfigs[p][s].type; for (int s = 0; s < 4; s++)
for (int i = 0; i < pads[p][s][padtype].numFFBindings; i++) { {
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me. int padtype = config.padConfigs[p][s].type;
ForceFeedbackBinding *ffb = &pads[p][s][padtype].ffBindings[i]; for (int i = 0; i < pads[p][s][padtype].numFFBindings; i++)
vibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); {
vibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); // Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
} ForceFeedbackBinding* ffb = &pads[p][s][padtype].ffBindings[i];
} vibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
} vibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
// Make sure at least 2 writes are queued, to update both motors. }
QueueWrite(); }
QueueWrite(); }
} // Make sure at least 2 writes are queued, to update both motors.
QueueWrite();
QueueWrite();
}
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) void SetEffect(ForceFeedbackBinding* binding, unsigned char force)
{ {
PadBindings pBackup = pads[0][0][0]; PadBindings pBackup = pads[0][0][0];
pads[0][0][0].ffBindings = binding; pads[0][0][0].ffBindings = binding;
pads[0][0][0].numFFBindings = 1; pads[0][0][0].numFFBindings = 1;
SetEffects(0, 0, binding->motor, 255); SetEffects(0, 0, binding->motor, 255);
pads[0][0][0] = pBackup; pads[0][0][0] = pBackup;
} }
void Deactivate() void Deactivate()
{ {
if (hFile != INVALID_HANDLE_VALUE) { if (hFile != INVALID_HANDLE_VALUE)
CancelIo(hFile); {
CloseHandle(hFile); CancelIo(hFile);
hFile = INVALID_HANDLE_VALUE; CloseHandle(hFile);
} hFile = INVALID_HANDLE_VALUE;
if (readop.hEvent) { }
CloseHandle(readop.hEvent); if (readop.hEvent)
} {
if (writeop.hEvent) { CloseHandle(readop.hEvent);
CloseHandle(writeop.hEvent); }
} if (writeop.hEvent)
writing = 0; {
writeQueued = 0; CloseHandle(writeop.hEvent);
memset(ps2Vibration, 0, sizeof(ps2Vibration)); }
vibration[0] = vibration[1] = 0; writing = 0;
writeQueued = 0;
memset(ps2Vibration, 0, sizeof(ps2Vibration));
vibration[0] = vibration[1] = 0;
FreeState(); FreeState();
active = 0; active = 0;
} }
~DualShock3Device() ~DualShock3Device()
{ {
} }
}; };
void EnumDualShock3s() void EnumDualShock3s()
{ {
if (!InitLibUsb()) if (!InitLibUsb())
return; return;
HidDeviceInfo *foundDevs = 0; HidDeviceInfo* foundDevs = 0;
int numDevs = FindHids(&foundDevs, VID, PID); int numDevs = FindHids(&foundDevs, VID, PID);
if (!numDevs) if (!numDevs)
return; return;
int index = 0; 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 && if (foundDevs[i].caps.FeatureReportByteLength == 49 &&
foundDevs[i].caps.OutputReportByteLength == 49) { foundDevs[i].caps.InputReportByteLength == 49 &&
wchar_t temp[100]; foundDevs[i].caps.OutputReportByteLength == 49)
wsprintfW(temp, L"DualShock 3 #%i", index + 1); {
dm->AddDevice(new DualShock3Device(index, temp, foundDevs[i].path)); wchar_t temp[100];
index++; wsprintfW(temp, L"DualShock 3 #%i", index + 1);
} dm->AddDevice(new DualShock3Device(index, temp, foundDevs[i].path));
free(foundDevs[i].path); index++;
} }
free(foundDevs); free(foundDevs[i].path);
}
free(foundDevs);
} }

View File

@ -45,40 +45,40 @@ typedef int64_t __int64;
#include <cstdarg> #include <cstdarg>
template <typename Array> template <typename Array>
void wsprintfW(Array &buf, const wchar_t *format, ...) void wsprintfW(Array& buf, const wchar_t* format, ...)
{ {
va_list a; va_list a;
va_start(a, format); 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); va_end(a);
} }
template <typename Array> template <typename Array>
void wsprintf(Array &buf, const wchar_t *format, ...) void wsprintf(Array& buf, const wchar_t* format, ...)
{ {
va_list a; va_list a;
va_start(a, format); 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); 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 ... // I didn't find a way to put ignore case ...
return wcscmp(w1, w2); return wcscmp(w1, w2);
} }
#include <sys/time.h> #include <sys/time.h>
static inline unsigned int timeGetTime() static inline unsigned int timeGetTime()
{ {
struct timeval now; struct timeval now;
gettimeofday(&now, NULL); 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 ... return (ms & 0xFFFFFFFF); // MS code is u32 ...
} }
#include "Utilities/Dependencies.h" #include "Utilities/Dependencies.h"
@ -87,7 +87,7 @@ static inline unsigned int timeGetTime()
#include <X11/Xutil.h> #include <X11/Xutil.h>
extern Display *GSdsp; extern Display* GSdsp;
extern Window GSwin; extern Window GSwin;
#endif #endif
@ -134,4 +134,4 @@ extern Window GSwin;
extern HINSTANCE hInst; extern HINSTANCE hInst;
#endif #endif
// Needed for config screen // Needed for config screen
void GetNameAndVersionString(wchar_t *out); void GetNameAndVersionString(wchar_t* out);

View File

@ -19,61 +19,69 @@
#include <setupapi.h> #include <setupapi.h>
#include <hidsdi.h> #include <hidsdi.h>
int FindHids(HidDeviceInfo **foundDevs, int vid, int pid) int FindHids(HidDeviceInfo** foundDevs, int vid, int pid)
{ {
GUID GUID_DEVINTERFACE_HID; GUID GUID_DEVINTERFACE_HID;
int numFoundDevs = 0; int numFoundDevs = 0;
*foundDevs = 0; *foundDevs = 0;
HidD_GetHidGuid(&GUID_DEVINTERFACE_HID); HidD_GetHidGuid(&GUID_DEVINTERFACE_HID);
HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hdev != INVALID_HANDLE_VALUE) { if (hdev != INVALID_HANDLE_VALUE)
SP_DEVICE_INTERFACE_DATA devInterfaceData; {
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); SP_DEVICE_INTERFACE_DATA devInterfaceData;
for (int i = 0; SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVINTERFACE_HID, i, &devInterfaceData); i++) { devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (int i = 0; SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVINTERFACE_HID, i, &devInterfaceData); i++)
{
DWORD size = 0; DWORD size = 0;
SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, 0, 0, &size, 0); SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, 0, 0, &size, 0);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !size) if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !size)
continue; continue;
SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(size); SP_DEVICE_INTERFACE_DETAIL_DATA* devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA*)malloc(size);
if (!devInterfaceDetails) if (!devInterfaceDetails)
continue; continue;
devInterfaceDetails->cbSize = sizeof(*devInterfaceDetails); devInterfaceDetails->cbSize = sizeof(*devInterfaceDetails);
SP_DEVINFO_DATA devInfoData; SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, devInterfaceDetails, size, &size, &devInfoData)) if (!SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, devInterfaceDetails, size, &size, &devInfoData))
continue; continue;
HANDLE hfile = CreateFile(devInterfaceDetails->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); 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) { if (hfile != INVALID_HANDLE_VALUE)
HIDD_ATTRIBUTES attributes; {
attributes.Size = sizeof(attributes); HIDD_ATTRIBUTES attributes;
if (HidD_GetAttributes(hfile, &attributes)) { attributes.Size = sizeof(attributes);
if (attributes.VendorID == vid && attributes.ProductID == pid) { if (HidD_GetAttributes(hfile, &attributes))
PHIDP_PREPARSED_DATA pData; {
HIDP_CAPS caps; if (attributes.VendorID == vid && attributes.ProductID == pid)
if (HidD_GetPreparsedData(hfile, &pData)) { {
if (HidP_GetCaps(pData, &caps) == HIDP_STATUS_SUCCESS) { PHIDP_PREPARSED_DATA pData;
if (numFoundDevs % 32 == 0) { HIDP_CAPS caps;
*foundDevs = (HidDeviceInfo *)realloc(*foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs)); if (HidD_GetPreparsedData(hfile, &pData))
} {
HidDeviceInfo *dev = &foundDevs[0][numFoundDevs++]; if (HidP_GetCaps(pData, &caps) == HIDP_STATUS_SUCCESS)
dev->caps = caps; {
dev->vid = attributes.VendorID; if (numFoundDevs % 32 == 0)
dev->pid = attributes.ProductID; {
dev->path = wcsdup(devInterfaceDetails->DevicePath); *foundDevs = (HidDeviceInfo*)realloc(*foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs));
} }
HidD_FreePreparsedData(pData); HidDeviceInfo* dev = &foundDevs[0][numFoundDevs++];
} dev->caps = caps;
} dev->vid = attributes.VendorID;
} dev->pid = attributes.ProductID;
CloseHandle(hfile); dev->path = wcsdup(devInterfaceDetails->DevicePath);
} }
free(devInterfaceDetails); HidD_FreePreparsedData(pData);
} }
SetupDiDestroyDeviceInfoList(hdev); }
} }
return numFoundDevs; CloseHandle(hfile);
}
free(devInterfaceDetails);
}
SetupDiDestroyDeviceInfoList(hdev);
}
return numFoundDevs;
} }

View File

@ -20,12 +20,12 @@
struct HidDeviceInfo struct HidDeviceInfo
{ {
HIDP_CAPS caps; HIDP_CAPS caps;
wchar_t *path; wchar_t* path;
unsigned short vid; unsigned short vid;
unsigned short pid; unsigned short pid;
}; };
int FindHids(HidDeviceInfo **foundDevs, int vid, int pid); int FindHids(HidDeviceInfo** foundDevs, int vid, int pid);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -31,42 +31,44 @@
* Still more effort than it's worth to port to Linux, however. * Still more effort than it's worth to port to Linux, however.
*/ */
enum PadType { enum PadType
DisabledPad, {
Dualshock2Pad, DisabledPad,
GuitarPad, Dualshock2Pad,
PopnPad, GuitarPad,
MousePad, PopnPad,
neGconPad, MousePad,
numPadTypes // total number of PadTypes. Add new PadType above this line. neGconPad,
numPadTypes // total number of PadTypes. Add new PadType above this line.
}; };
// Mostly match DirectInput8 values. Note that these are for physical controls. // Mostly match DirectInput8 values. Note that these are for physical controls.
// One physical axis maps to 3 virtual ones, and one physical POV control maps to // One physical axis maps to 3 virtual ones, and one physical POV control maps to
// 4 virtual ones. // 4 virtual ones.
enum ControlType { enum ControlType
NO_CONTROL = 0, {
// Axes are ints. Relative axes are for mice, mice wheels, etc, NO_CONTROL = 0,
// and are always reported relative to their last value. // Axes are ints. Relative axes are for mice, mice wheels, etc,
// Absolute axes range from -65536 to 65536 and are absolute positions, // and are always reported relative to their last value.
// like for joysticks and pressure sensitive buttons. // Absolute axes range from -65536 to 65536 and are absolute positions,
RELAXIS = 1, // like for joysticks and pressure sensitive buttons.
ABSAXIS = 2, RELAXIS = 1,
ABSAXIS = 2,
// Buttons range from 0 to 65536. // Buttons range from 0 to 65536.
PSHBTN = 4, PSHBTN = 4,
TGLBTN = 8, TGLBTN = 8,
// POV controls are ints, values range from -1 to 36000. // POV controls are ints, values range from -1 to 36000.
// -1 means not pressed, otherwise it's an angle. // -1 means not pressed, otherwise it's an angle.
// For easy DirectInput compatibility, anything outside. // For easy DirectInput compatibility, anything outside.
// that range is treated as -1 (Though 36000-37000 is treated // that range is treated as -1 (Though 36000-37000 is treated
// like 0 to 1000, just in case). // like 0 to 1000, just in case).
POV = 16, POV = 16,
// Pressure sensitive buttons. Only a different type because // Pressure sensitive buttons. Only a different type because
// they have configurable dead zones, unlike push or toggle buttons. // they have configurable dead zones, unlike push or toggle buttons.
PRESSURE_BTN = 32, PRESSURE_BTN = 32,
}; };
// Masks to determine button type. Don't need one for POV. // Masks to determine button type. Don't need one for POV.
@ -76,12 +78,12 @@ enum ControlType {
struct Binding struct Binding
{ {
int controlIndex; int controlIndex;
int command; int command;
int sensitivity; int sensitivity;
int deadZone; int deadZone;
int skipDeadZone; int skipDeadZone;
unsigned char rapidFire; unsigned char rapidFire;
}; };
#define UID_AXIS (1U << 31) #define UID_AXIS (1U << 31)
@ -101,13 +103,13 @@ struct Binding
// all directions are assigned individually. // all directions are assigned individually.
struct VirtualControl struct VirtualControl
{ {
// Unique id for control, given device. Based on source control's id, // 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 // 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, // a button or a pov/axis control's individual button), and an index,
// if the control is split. // if the control is split.
unsigned int uid; unsigned int uid;
// virtual key code. 0 if none. // virtual key code. 0 if none.
int physicalControlIndex; int physicalControlIndex;
}; };
// Need one for each button, axis, and pov control. // Need one for each button, axis, and pov control.
@ -117,48 +119,51 @@ struct VirtualControl
// needed. // needed.
struct PhysicalControl struct PhysicalControl
{ {
// index of the first virtual control corresponding to this. // index of the first virtual control corresponding to this.
// Buttons have 1 virtual control, axes 3, and povs 5, all // Buttons have 1 virtual control, axes 3, and povs 5, all
// in a row. // in a row.
int baseVirtualControlIndex; int baseVirtualControlIndex;
ControlType type; ControlType type;
// id. Must be unique for control type. // id. Must be unique for control type.
// short so can be combined with other values to get // short so can be combined with other values to get
// uid for virtual controls. // uid for virtual controls.
unsigned short id; unsigned short id;
unsigned short vkey; unsigned short vkey;
wchar_t *name; wchar_t* name;
}; };
enum DeviceAPI { enum DeviceAPI
NO_API = 0, {
DI = 1, NO_API = 0,
WM = 2, DI = 1,
RAW = 3, WM = 2,
XINPUT = 4, RAW = 3,
DS3 = 5, XINPUT = 4,
// Not currently used. DS3 = 5,
LLHOOK = 6, // Not currently used.
// Not a real API, obviously. Only used with keyboards, LLHOOK = 6,
// to ignore individual buttons. Wrapper itself takes care // Not a real API, obviously. Only used with keyboards,
// of ignoring bound keys. Otherwise, works normally. // to ignore individual buttons. Wrapper itself takes care
IGNORE_KEYBOARD = 7, // of ignoring bound keys. Otherwise, works normally.
// XXX IGNORE_KEYBOARD = 7,
LNX_KEYBOARD = 16, // XXX
LNX_JOY = 17, LNX_KEYBOARD = 16,
LNX_JOY = 17,
}; };
enum DeviceType { enum DeviceType
NO_DEVICE = 0, {
KEYBOARD = 1, NO_DEVICE = 0,
MOUSE = 2, KEYBOARD = 1,
OTHER = 3 MOUSE = 2,
OTHER = 3
}; };
enum EffectType { enum EffectType
EFFECT_CONSTANT, {
EFFECT_PERIODIC, EFFECT_CONSTANT,
EFFECT_RAMP EFFECT_PERIODIC,
EFFECT_RAMP
}; };
// force range sfrom -BASE_SENSITIVITY to BASE_SENSITIVITY. // force range sfrom -BASE_SENSITIVITY to BASE_SENSITIVITY.
@ -167,32 +172,32 @@ enum EffectType {
// the axis with minimum force (Possibly 0 force), if applicable. // the axis with minimum force (Possibly 0 force), if applicable.
struct AxisEffectInfo struct AxisEffectInfo
{ {
int force; int force;
}; };
struct ForceFeedbackBinding struct ForceFeedbackBinding
{ {
AxisEffectInfo *axes; AxisEffectInfo* axes;
int effectIndex; int effectIndex;
unsigned char motor; unsigned char motor;
}; };
// Bindings listed by effect, so I don't have to bother with // Bindings listed by effect, so I don't have to bother with
// indexing effects. // indexing effects.
struct ForceFeedbackEffectType struct ForceFeedbackEffectType
{ {
wchar_t *displayName; wchar_t* displayName;
// Because I'm lazy, can only have ASCII characters and no spaces. // Because I'm lazy, can only have ASCII characters and no spaces.
wchar_t *effectID; wchar_t* effectID;
// constant, ramp, or periodic // constant, ramp, or periodic
EffectType type; EffectType type;
}; };
struct ForceFeedbackAxis struct ForceFeedbackAxis
{ {
wchar_t *displayName; wchar_t* displayName;
int id; int id;
}; };
// Used both for active devices and for sets of settings for devices. // Used both for active devices and for sets of settings for devices.
@ -203,32 +208,32 @@ struct ForceFeedbackAxis
struct PadBindings struct PadBindings
{ {
Binding *bindings; Binding* bindings;
int numBindings; int numBindings;
ForceFeedbackBinding *ffBindings; ForceFeedbackBinding* ffBindings;
int numFFBindings; int numFFBindings;
}; };
class WndProcEater; class WndProcEater;
struct InitInfo struct InitInfo
{ {
// 1 when binding key to ignore. // 1 when binding key to ignore.
int bindingIgnore; int bindingIgnore;
// 1 when binding. // 1 when binding.
int binding; int binding;
#ifdef _MSC_VER #ifdef _MSC_VER
HWND hWndTop; HWND hWndTop;
// For config screen, need to eat button's message handling. // For config screen, need to eat button's message handling.
//HWND hWndButton; //HWND hWndButton;
WndProcEater *hWndProc; WndProcEater* hWndProc;
#else #else
// Linux equivalent to HWND // Linux equivalent to HWND
Display *GSdsp; Display* GSdsp;
Window GSwin; Window GSwin;
#endif #endif
}; };
@ -238,165 +243,165 @@ struct InitInfo
class Device class Device
{ {
public: public:
DeviceAPI api; DeviceAPI api;
DeviceType type; DeviceType type;
char active; char active;
char attached; char attached;
// Based on input modes. // Based on input modes.
char enabled; char enabled;
#ifdef _MSC_VER #ifdef _MSC_VER
// Not all devices need to subclass the windproc, but most do so might as well // Not all devices need to subclass the windproc, but most do so might as well
// put it here... --air // put it here... --air
WndProcEater *hWndProc; WndProcEater* hWndProc;
#endif #endif
union union
{ {
// Allows for one loop to compare all 3 in order. // Allows for one loop to compare all 3 in order.
wchar_t *IDs[3]; wchar_t* IDs[3];
struct struct
{ {
// Same as DisplayName, when not given. Absolutely must be unique. // Same as DisplayName, when not given. Absolutely must be unique.
// Used for loading/saving controls. If matches, all other strings // Used for loading/saving controls. If matches, all other strings
// are ignored, so must be unique. // are ignored, so must be unique.
wchar_t *instanceID; wchar_t* instanceID;
// Not required. Used when a device's instance id changes, doesn't have to // Not required. Used when a device's instance id changes, doesn't have to
// be unique. For devices that can only have one instance, not needed. // be unique. For devices that can only have one instance, not needed.
wchar_t *productID; wchar_t* productID;
wchar_t *displayName; wchar_t* displayName;
}; };
}; };
PadBindings pads[2][4][numPadTypes]; PadBindings pads[2][4][numPadTypes];
// Virtual controls. All basically act like pressure sensitivity buttons, with // Virtual controls. All basically act like pressure sensitivity buttons, with
// values between 0 and 2^16. 2^16 is fully down, 0 is up. Larger values // values between 0 and 2^16. 2^16 is fully down, 0 is up. Larger values
// are allowed, but *only* for absolute axes (Which don't support the flip checkbox). // are allowed, but *only* for absolute axes (Which don't support the flip checkbox).
// Each control on a device must have a unique id, used for binding. // Each control on a device must have a unique id, used for binding.
VirtualControl *virtualControls; VirtualControl* virtualControls;
int numVirtualControls; int numVirtualControls;
int *virtualControlState; int* virtualControlState;
int *oldVirtualControlState; int* oldVirtualControlState;
PhysicalControl *physicalControls; PhysicalControl* physicalControls;
int numPhysicalControls; int numPhysicalControls;
int *physicalControlState; int* physicalControlState;
ForceFeedbackEffectType *ffEffectTypes; ForceFeedbackEffectType* ffEffectTypes;
int numFFEffectTypes; int numFFEffectTypes;
ForceFeedbackAxis *ffAxes; ForceFeedbackAxis* ffAxes;
int numFFAxes; int numFFAxes;
void AddFFAxis(const wchar_t *displayName, int id); void AddFFAxis(const wchar_t* displayName, int id);
void AddFFEffectType(const wchar_t *displayName, const wchar_t *effectID, EffectType type); void AddFFEffectType(const wchar_t* displayName, const wchar_t* effectID, EffectType type);
Device(DeviceAPI, DeviceType, const wchar_t *displayName, const wchar_t *instanceID = 0, const wchar_t *deviceID = 0); Device(DeviceAPI, DeviceType, const wchar_t* displayName, const wchar_t* instanceID = 0, const wchar_t* deviceID = 0);
virtual ~Device(); virtual ~Device();
// Allocates memory for old and new state, sets everything to 0. // Allocates memory for old and new state, sets everything to 0.
// all old states are in one array, buttons, axes, and then POVs. // all old states are in one array, buttons, axes, and then POVs.
// start of each section is int aligned. This makes it DirectInput // start of each section is int aligned. This makes it DirectInput
// compatible. // compatible.
void AllocState(); void AllocState();
// Doesn't actually flip. Copies current state to old state. // Doesn't actually flip. Copies current state to old state.
void FlipState(); void FlipState();
// Frees state variables. // Frees state variables.
void FreeState(); void FreeState();
ForceFeedbackEffectType *GetForcefeedbackEffect(wchar_t *id); ForceFeedbackEffectType* GetForcefeedbackEffect(wchar_t* id);
ForceFeedbackAxis *GetForceFeedbackAxis(int id); ForceFeedbackAxis* GetForceFeedbackAxis(int id);
VirtualControl *GetVirtualControl(unsigned int uid); VirtualControl* GetVirtualControl(unsigned int uid);
PhysicalControl *AddPhysicalControl(ControlType type, unsigned short id, unsigned short vkey, const wchar_t *name = 0); PhysicalControl* AddPhysicalControl(ControlType type, unsigned short id, unsigned short vkey, const wchar_t* name = 0);
VirtualControl *AddVirtualControl(unsigned int uid, int physicalControlIndex); VirtualControl* AddVirtualControl(unsigned int uid, int physicalControlIndex);
virtual wchar_t *GetVirtualControlName(VirtualControl *c); virtual wchar_t* GetVirtualControlName(VirtualControl* c);
virtual wchar_t *GetPhysicalControlName(PhysicalControl *c); virtual wchar_t* GetPhysicalControlName(PhysicalControl* c);
void CalcVirtualState(); void CalcVirtualState();
virtual int Activate(InitInfo *args) virtual int Activate(InitInfo* args)
{ {
return 0; return 0;
} }
inline virtual void Deactivate() inline virtual void Deactivate()
{ {
FreeState(); FreeState();
active = 0; active = 0;
} }
// Default update proc. All that's needed for post-based APIs. // Default update proc. All that's needed for post-based APIs.
inline virtual int Update() inline virtual int Update()
{ {
return active; return active;
} }
// force is from -FULLY_DOWN to FULLY_DOWN. // force is from -FULLY_DOWN to FULLY_DOWN.
// Either function can be overridden. Second one by default calls the first // Either function can be overridden. Second one by default calls the first
// for every bound effect that's affected. // for every bound effect that's affected.
// Note: Only used externally for binding, so if override the other one, can assume // Note: Only used externally for binding, so if override the other one, can assume
// all other forces are currently 0. // all other forces are currently 0.
inline virtual void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {} inline virtual void SetEffect(ForceFeedbackBinding* binding, unsigned char force) {}
virtual void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force); virtual void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force);
// Called after reading. Basically calls FlipState(). // Called after reading. Basically calls FlipState().
// Some device types (Those that don't incrementally update) // Some device types (Those that don't incrementally update)
// could call FlipState elsewhere, but this makes it simpler to ignore // could call FlipState elsewhere, but this makes it simpler to ignore
// while binding. // while binding.
virtual void PostRead(); virtual void PostRead();
}; };
class InputDeviceManager class InputDeviceManager
{ {
public: public:
Device **devices; Device** devices;
int numDevices; int numDevices;
void ClearDevices(); void ClearDevices();
// When refreshing devices, back up old devices, then // When refreshing devices, back up old devices, then
// populate this with new devices, then call copy bindings. // populate this with new devices, then call copy bindings.
// All old bindings are copied to matching devices. // All old bindings are copied to matching devices.
// When old devices are missing, I do a slightly more careful search // When old devices are missing, I do a slightly more careful search
// using productIDs and then (in desperation) displayName. // using productIDs and then (in desperation) displayName.
// Finally create new dummy devices if no matches found. // Finally create new dummy devices if no matches found.
void CopyBindings(int numDevices, Device **devices); void CopyBindings(int numDevices, Device** devices);
InputDeviceManager(); InputDeviceManager();
~InputDeviceManager(); ~InputDeviceManager();
void AddDevice(Device *d); void AddDevice(Device* d);
Device *GetActiveDevice(InitInfo *info, unsigned int *uid, int *index, int *value); Device* GetActiveDevice(InitInfo* info, unsigned int* uid, int* index, int* value);
void Update(InitInfo *initInfo); void Update(InitInfo* initInfo);
// Called after reading state, after Update(). // Called after reading state, after Update().
void PostRead(); void PostRead();
void SetEffect(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force); void SetEffect(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force);
// Update does this as needed. // Update does this as needed.
// void GetInput(void *v); // void GetInput(void *v);
void ReleaseInput(); void ReleaseInput();
void DisableDevice(int index); void DisableDevice(int index);
inline void EnableDevice(int i) inline void EnableDevice(int i)
{ {
devices[i]->enabled = 1; devices[i]->enabled = 1;
} }
void EnableDevices(DeviceType type, DeviceAPI api); void EnableDevices(DeviceType type, DeviceAPI api);
void DisableAllDevices(); void DisableAllDevices();
}; };
extern InputDeviceManager *dm; extern InputDeviceManager* dm;
#endif #endif

View File

@ -36,65 +36,70 @@ static keyEvent queuedEvents[EVENT_QUEUE_LEN];
void QueueKeyEvent(int key, int event) void QueueKeyEvent(int key, int event)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
if (!csInitialized) { if (!csInitialized)
csInitialized = 1; {
InitializeCriticalSection(&cSection); csInitialized = 1;
} InitializeCriticalSection(&cSection);
EnterCriticalSection(&cSection); }
EnterCriticalSection(&cSection);
#else #else
std::lock_guard<std::mutex> lock(cSection); std::lock_guard<std::mutex> lock(cSection);
#endif #endif
// Don't queue events if escape is on top of queue. This is just for safety // Don't queue events if escape is on top of queue. This is just for safety
// purposes when a game is killing the emulator for whatever reason. // purposes when a game is killing the emulator for whatever reason.
if (nextQueuedEvent == lastQueuedEvent || if (nextQueuedEvent == lastQueuedEvent ||
queuedEvents[nextQueuedEvent].key != VK_ESCAPE || queuedEvents[nextQueuedEvent].key != VK_ESCAPE ||
queuedEvents[nextQueuedEvent].evt != KEYPRESS) { queuedEvents[nextQueuedEvent].evt != KEYPRESS)
// Clear queue on escape down, bringing escape to front. May do something {
// with shift/ctrl/alt and F-keys, later. // Clear queue on escape down, bringing escape to front. May do something
if (event == KEYPRESS && key == VK_ESCAPE) { // with shift/ctrl/alt and F-keys, later.
nextQueuedEvent = lastQueuedEvent; if (event == KEYPRESS && key == VK_ESCAPE)
} {
nextQueuedEvent = lastQueuedEvent;
}
queuedEvents[lastQueuedEvent].key = key; queuedEvents[lastQueuedEvent].key = key;
queuedEvents[lastQueuedEvent].evt = event; queuedEvents[lastQueuedEvent].evt = event;
lastQueuedEvent = (lastQueuedEvent + 1) % EVENT_QUEUE_LEN; lastQueuedEvent = (lastQueuedEvent + 1) % EVENT_QUEUE_LEN;
// If queue wrapped around, remove last element. // If queue wrapped around, remove last element.
if (nextQueuedEvent == lastQueuedEvent) { if (nextQueuedEvent == lastQueuedEvent)
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN; {
} nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
} }
}
#ifdef _MSC_VER #ifdef _MSC_VER
LeaveCriticalSection(&cSection); LeaveCriticalSection(&cSection);
#endif #endif
} }
int GetQueuedKeyEvent(keyEvent *event) int GetQueuedKeyEvent(keyEvent* event)
{ {
if (lastQueuedEvent == nextQueuedEvent) if (lastQueuedEvent == nextQueuedEvent)
return 0; return 0;
#ifdef _MSC_VER #ifdef _MSC_VER
EnterCriticalSection(&cSection); EnterCriticalSection(&cSection);
#else #else
std::lock_guard<std::mutex> lock(cSection); std::lock_guard<std::mutex> lock(cSection);
#endif #endif
*event = queuedEvents[nextQueuedEvent]; *event = queuedEvents[nextQueuedEvent];
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN; nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
#ifdef _MSC_VER #ifdef _MSC_VER
LeaveCriticalSection(&cSection); LeaveCriticalSection(&cSection);
#endif #endif
return 1; return 1;
} }
void ClearKeyQueue() void ClearKeyQueue()
{ {
lastQueuedEvent = nextQueuedEvent; lastQueuedEvent = nextQueuedEvent;
#ifdef _MSC_VER #ifdef _MSC_VER
if (csInitialized) { if (csInitialized)
DeleteCriticalSection(&cSection); {
csInitialized = 0; DeleteCriticalSection(&cSection);
} csInitialized = 0;
}
#endif #endif
} }

View File

@ -18,13 +18,13 @@
// but takes little enough effort to be safe... // but takes little enough effort to be safe...
void QueueKeyEvent(int key, int event); void QueueKeyEvent(int key, int event);
int GetQueuedKeyEvent(keyEvent *event); int GetQueuedKeyEvent(keyEvent* event);
// Cleans up as well as clears queue. // Cleans up as well as clears queue.
void ClearKeyQueue(); void ClearKeyQueue();
#ifdef __linux__ #ifdef __linux__
void R_QueueKeyEvent(const keyEvent &event); void R_QueueKeyEvent(const keyEvent& event);
int R_GetQueuedKeyEvent(keyEvent *event); int R_GetQueuedKeyEvent(keyEvent* event);
void R_ClearKeyQueue(); void R_ClearKeyQueue();
#endif #endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,63 +16,63 @@
#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H
extern const wchar_t *padTypes[numPadTypes]; extern const wchar_t* padTypes[numPadTypes];
struct PadConfig struct PadConfig
{ {
PadType type; PadType type;
}; };
struct GeneralConfig struct GeneralConfig
{ {
public: public:
PadConfig padConfigs[2][4]; PadConfig padConfigs[2][4];
int deviceSelect[2][4]; int deviceSelect[2][4];
DeviceAPI keyboardApi; DeviceAPI keyboardApi;
DeviceAPI mouseApi; DeviceAPI mouseApi;
// Derived value, calculated by GetInput(). // Derived value, calculated by GetInput().
u8 configureOnBind; u8 configureOnBind;
bool bind; bool bind;
bool specialInputs[2][4]; bool specialInputs[2][4];
union union
{ {
struct struct
{ {
u8 forceHide; u8 forceHide;
u8 mouseUnfocus; u8 mouseUnfocus;
u8 background; u8 background;
u8 multipleBinding; u8 multipleBinding;
struct struct
{ {
u8 directInput; u8 directInput;
u8 xInput; u8 xInput;
u8 dualShock3; u8 dualShock3;
} gameApis; } gameApis;
u8 multitap[2]; u8 multitap[2];
u8 debug; u8 debug;
u8 GH2; u8 GH2;
}; };
u8 bools[15]; u8 bools[15];
}; };
wchar_t lastSaveConfigPath[MAX_PATH + 1]; wchar_t lastSaveConfigPath[MAX_PATH + 1];
wchar_t lastSaveConfigFileName[MAX_PATH + 1]; wchar_t lastSaveConfigFileName[MAX_PATH + 1];
}; };
extern GeneralConfig config; extern GeneralConfig config;
void UnloadConfigs(); void UnloadConfigs();
int LoadSettings(int force = 0, wchar_t *file = 0); int LoadSettings(int force = 0, wchar_t* file = 0);
// Refreshes the set of enabled devices. // Refreshes the set of enabled devices.
void RefreshEnabledDevices(int updateDeviceList = 0); void RefreshEnabledDevices(int updateDeviceList = 0);

View File

@ -23,50 +23,50 @@
#include "WindowsKeyboard.h" #include "WindowsKeyboard.h"
#include "WindowsMouse.h" #include "WindowsMouse.h"
ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output); ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* output);
int GetRawKeyboards(HWND hWnd) int GetRawKeyboards(HWND hWnd)
{ {
RAWINPUTDEVICE Rid; RAWINPUTDEVICE Rid;
Rid.hwndTarget = hWnd; Rid.hwndTarget = hWnd;
Rid.dwFlags = 0; Rid.dwFlags = 0;
Rid.usUsagePage = 0x01; Rid.usUsagePage = 0x01;
Rid.usUsage = 0x06; Rid.usUsage = 0x06;
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid)); return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
} }
void ReleaseRawKeyboards() void ReleaseRawKeyboards()
{ {
RAWINPUTDEVICE Rid; RAWINPUTDEVICE Rid;
Rid.hwndTarget = 0; Rid.hwndTarget = 0;
Rid.dwFlags = RIDEV_REMOVE; Rid.dwFlags = RIDEV_REMOVE;
Rid.usUsagePage = 0x01; Rid.usUsagePage = 0x01;
Rid.usUsage = 0x06; Rid.usUsage = 0x06;
RegisterRawInputDevices(&Rid, 1, sizeof(Rid)); RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
} }
int GetRawMice(HWND hWnd) int GetRawMice(HWND hWnd)
{ {
RAWINPUTDEVICE Rid; RAWINPUTDEVICE Rid;
Rid.hwndTarget = hWnd; Rid.hwndTarget = hWnd;
Rid.dwFlags = RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE; Rid.dwFlags = RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE;
Rid.usUsagePage = 0x01; Rid.usUsagePage = 0x01;
Rid.usUsage = 0x02; Rid.usUsage = 0x02;
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid)); return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
} }
void ReleaseRawMice() void ReleaseRawMice()
{ {
RAWINPUTDEVICE Rid; RAWINPUTDEVICE Rid;
Rid.hwndTarget = 0; Rid.hwndTarget = 0;
Rid.dwFlags = RIDEV_REMOVE; Rid.dwFlags = RIDEV_REMOVE;
Rid.usUsagePage = 0x01; Rid.usUsagePage = 0x01;
Rid.usUsage = 0x02; Rid.usUsage = 0x02;
RegisterRawInputDevices(&Rid, 1, sizeof(Rid)); RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
} }
// Count of active raw keyboard devices. // Count of active raw keyboard devices.
@ -78,253 +78,290 @@ static int rawMouseActivatedCount = 0;
class RawInputKeyboard : public WindowsKeyboard class RawInputKeyboard : public WindowsKeyboard
{ {
public: public:
HANDLE hDevice; HANDLE hDevice;
RawInputKeyboard(HANDLE hDevice, wchar_t *name, wchar_t *instanceID = 0) RawInputKeyboard(HANDLE hDevice, wchar_t* name, wchar_t* instanceID = 0)
: WindowsKeyboard(RAW, name, instanceID) : WindowsKeyboard(RAW, name, instanceID)
{ {
this->hDevice = hDevice; this->hDevice = hDevice;
} }
int Activate(InitInfo *initInfo) int Activate(InitInfo* initInfo)
{ {
Deactivate(); Deactivate();
hWndProc = initInfo->hWndProc; hWndProc = initInfo->hWndProc;
active = 1; active = 1;
if (!rawKeyboardActivatedCount++) { if (!rawKeyboardActivatedCount++)
if (!rawMouseActivatedCount) {
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES); if (!rawMouseActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!GetRawKeyboards(hWndProc->hWndEaten)) { if (!GetRawKeyboards(hWndProc->hWndEaten))
Deactivate(); {
return 0; Deactivate();
} return 0;
} }
}
InitState(); InitState();
return 1; return 1;
} }
void Deactivate() void Deactivate()
{ {
FreeState(); FreeState();
if (active) { if (active)
active = 0; {
rawKeyboardActivatedCount--; active = 0;
if (!rawKeyboardActivatedCount) { rawKeyboardActivatedCount--;
ReleaseRawKeyboards(); if (!rawKeyboardActivatedCount)
if (!rawMouseActivatedCount) {
hWndProc->ReleaseExtraProc(RawInputWndProc); ReleaseRawKeyboards();
} if (!rawMouseActivatedCount)
} hWndProc->ReleaseExtraProc(RawInputWndProc);
} }
}
}
}; };
class RawInputMouse : public WindowsMouse class RawInputMouse : public WindowsMouse
{ {
public: public:
HANDLE hDevice; HANDLE hDevice;
RawInputMouse(HANDLE hDevice, wchar_t *name, wchar_t *instanceID = 0, wchar_t *productID = 0) RawInputMouse(HANDLE hDevice, wchar_t* name, wchar_t* instanceID = 0, wchar_t* productID = 0)
: WindowsMouse(RAW, 0, name, instanceID, productID) : WindowsMouse(RAW, 0, name, instanceID, productID)
{ {
this->hDevice = hDevice; this->hDevice = hDevice;
} }
int Activate(InitInfo *initInfo) int Activate(InitInfo* initInfo)
{ {
Deactivate(); Deactivate();
hWndProc = initInfo->hWndProc; hWndProc = initInfo->hWndProc;
active = 1; active = 1;
// Have to be careful with order. At worst, one unmatched call to ReleaseRawMice on // Have to be careful with order. At worst, one unmatched call to ReleaseRawMice on
// EatWndProc fail. In all other cases, no unmatched initialization/cleanup // EatWndProc fail. In all other cases, no unmatched initialization/cleanup
// lines. // lines.
if (!rawMouseActivatedCount++) { if (!rawMouseActivatedCount++)
GetMouseCapture(hWndProc->hWndEaten); {
if (!rawKeyboardActivatedCount) GetMouseCapture(hWndProc->hWndEaten);
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES); if (!rawKeyboardActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!GetRawMice(hWndProc->hWndEaten)) { if (!GetRawMice(hWndProc->hWndEaten))
Deactivate(); {
return 0; Deactivate();
} return 0;
} }
}
AllocState(); AllocState();
return 1; return 1;
} }
void Deactivate() void Deactivate()
{ {
FreeState(); FreeState();
if (active) { if (active)
active = 0; {
rawMouseActivatedCount--; active = 0;
if (!rawMouseActivatedCount) { rawMouseActivatedCount--;
ReleaseRawMice(); if (!rawMouseActivatedCount)
ReleaseMouseCapture(); {
if (!rawKeyboardActivatedCount) { ReleaseRawMice();
hWndProc->ReleaseExtraProc(RawInputWndProc); ReleaseMouseCapture();
} if (!rawKeyboardActivatedCount)
} {
} hWndProc->ReleaseExtraProc(RawInputWndProc);
} }
}
}
}
}; };
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 (uMsg == WM_INPUT)
if (GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT) { {
RAWINPUT in; if (GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT)
unsigned int size = sizeof(RAWINPUT); {
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &in, &size, sizeof(RAWINPUTHEADER)) > 0) { RAWINPUT in;
for (int i = 0; i < dm->numDevices; i++) { unsigned int size = sizeof(RAWINPUT);
Device *dev = dm->devices[i]; if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &in, &size, sizeof(RAWINPUTHEADER)) > 0)
if (dev->api != RAW || !dev->active) {
continue; for (int i = 0; i < dm->numDevices; i++)
if (in.header.dwType == RIM_TYPEKEYBOARD && dev->type == KEYBOARD) { {
RawInputKeyboard *rik = (RawInputKeyboard *)dev; Device* dev = dm->devices[i];
if (rik->hDevice != in.header.hDevice) if (dev->api != RAW || !dev->active)
continue; continue;
if (in.header.dwType == RIM_TYPEKEYBOARD && dev->type == KEYBOARD)
{
RawInputKeyboard* rik = (RawInputKeyboard*)dev;
if (rik->hDevice != in.header.hDevice)
continue;
u32 uMsg = in.data.keyboard.Message; u32 uMsg = in.data.keyboard.Message;
if (!(in.data.keyboard.VKey >> 8)) if (!(in.data.keyboard.VKey >> 8))
rik->UpdateKey((u8)in.data.keyboard.VKey, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)); 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; else if (in.header.dwType == RIM_TYPEMOUSE && dev->type == MOUSE)
if (rim->hDevice != in.header.hDevice) {
continue; RawInputMouse* rim = (RawInputMouse*)dev;
if (in.data.mouse.usFlags) { if (rim->hDevice != in.header.hDevice)
// Never been set for me, and specs on what most of them continue;
// actually mean is sorely lacking. Also, specs erroneously if (in.data.mouse.usFlags)
// indicate MOUSE_MOVE_RELATIVE is a flag, when it's really {
// 0... // Never been set for me, and specs on what most of them
continue; // actually mean is sorely lacking. Also, specs erroneously
} // indicate MOUSE_MOVE_RELATIVE is a flag, when it's really
// 0...
continue;
}
unsigned short buttons = in.data.mouse.usButtonFlags & 0x3FF; unsigned short buttons = in.data.mouse.usButtonFlags & 0x3FF;
int button = 0; int button = 0;
while (buttons) { while (buttons)
if (buttons & 3) { {
// 2 is up, 1 is down. Up takes precedence over down. if (buttons & 3)
rim->UpdateButton(button, !(buttons & 2)); {
} // 2 is up, 1 is down. Up takes precedence over down.
button++; rim->UpdateButton(button, !(buttons & 2));
buttons >>= 2; }
} button++;
if (in.data.mouse.usButtonFlags & RI_MOUSE_WHEEL) { buttons >>= 2;
rim->UpdateAxis(2, ((short)in.data.mouse.usButtonData) / WHEEL_DELTA); }
} if (in.data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
if (in.data.mouse.lLastX || in.data.mouse.lLastY) { {
rim->UpdateAxis(0, in.data.mouse.lLastX); rim->UpdateAxis(2, ((short)in.data.mouse.usButtonData) / WHEEL_DELTA);
rim->UpdateAxis(1, in.data.mouse.lLastY); }
} if (in.data.mouse.lLastX || in.data.mouse.lLastY)
} {
} rim->UpdateAxis(0, in.data.mouse.lLastX);
} rim->UpdateAxis(1, in.data.mouse.lLastY);
} }
} 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; }
memset(dev->physicalControlState, 0, sizeof(int) * dev->numPhysicalControls); else if (uMsg == WM_ACTIVATE)
} {
} else if (uMsg == WM_SIZE && rawMouseActivatedCount) { for (int i = 0; i < dm->numDevices; i++)
// Doesn't really matter for raw mice, as I disable legacy stuff, but shouldn't hurt. {
WindowsMouse::WindowResized(hWnd); Device* dev = dm->devices[i];
} if (dev->api != RAW || dev->physicalControlState == 0)
continue;
memset(dev->physicalControlState, 0, sizeof(int) * dev->numPhysicalControls);
}
}
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);
}
return CONTINUE_BLISSFULLY; return CONTINUE_BLISSFULLY;
} }
void EnumRawInputDevices() void EnumRawInputDevices()
{ {
int count = 0; int count = 0;
if (GetRawInputDeviceList(0, (unsigned int *)&count, sizeof(RAWINPUTDEVICELIST)) != (UINT)-1 && count > 0) { 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* instanceID = (wchar_t*)malloc(41000 * sizeof(wchar_t));
wchar_t *displayName = keyName + 10000; wchar_t* keyName = instanceID + 11000;
wchar_t *productID = displayName + 10000; 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 keyboardCount = 1;
int mouseCount = 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. // Not necessary, but reminder that count is -1 on failure.
if (count > 0) { if (count > 0)
for (int i = 0; i < count; i++) { {
if (list[i].dwType != RIM_TYPEKEYBOARD && list[i].dwType != RIM_TYPEMOUSE) for (int i = 0; i < count; i++)
continue; {
if (list[i].dwType != RIM_TYPEKEYBOARD && list[i].dwType != RIM_TYPEMOUSE)
continue;
UINT bufferLen = 10000; UINT bufferLen = 10000;
int nameLen = GetRawInputDeviceInfo(list[i].hDevice, RIDI_DEVICENAME, instanceID, &bufferLen); int nameLen = GetRawInputDeviceInfo(list[i].hDevice, RIDI_DEVICENAME, instanceID, &bufferLen);
if (nameLen >= 4) { if (nameLen >= 4)
// nameLen includes terminating null. {
nameLen--; // nameLen includes terminating null.
nameLen--;
// Strip out GUID parts of instanceID to make it a generic product id, // Strip out GUID parts of instanceID to make it a generic product id,
// and reformat it to point to registry entry containing device description. // and reformat it to point to registry entry containing device description.
wcscpy(productID, instanceID); wcscpy(productID, instanceID);
wchar_t *temp = 0; 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) wchar_t* s = wcschr(productID, '#');
break; if (!s)
*s = '\\'; break;
if (j == 2) { *s = '\\';
*s = 0; if (j == 2)
} {
if (j == 1) *s = 0;
temp = s; }
} if (j == 1)
temp = s;
}
wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID + 3); wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID + 3);
if (temp) if (temp)
*temp = 0; *temp = 0;
int haveDescription = 0; int haveDescription = 0;
HKEY hKey; HKEY hKey;
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) { if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey))
DWORD type; {
DWORD len = 10000 * sizeof(wchar_t); DWORD type;
if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE *)displayName, &len) && DWORD len = 10000 * sizeof(wchar_t);
len && type == REG_SZ) { if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE*)displayName, &len) &&
wchar_t *temp2 = wcsrchr(displayName, ';'); len && type == REG_SZ)
if (!temp2) {
temp2 = displayName; wchar_t* temp2 = wcsrchr(displayName, ';');
else if (!temp2)
temp2++; temp2 = displayName;
// Could do without this, but more effort than it's worth. else
wcscpy(keyName, temp2); temp2++;
haveDescription = 1; // Could do without this, but more effort than it's worth.
} wcscpy(keyName, temp2);
RegCloseKey(hKey); haveDescription = 1;
} }
if (list[i].dwType == RIM_TYPEKEYBOARD) { RegCloseKey(hKey);
if (!haveDescription) }
wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++); if (list[i].dwType == RIM_TYPEKEYBOARD)
else {
wsprintfW(displayName, L"Raw KB: %s", keyName); if (!haveDescription)
dm->AddDevice(new RawInputKeyboard(list[i].hDevice, displayName, instanceID)); wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++);
} else if (list[i].dwType == RIM_TYPEMOUSE) { else
if (!haveDescription) wsprintfW(displayName, L"Raw KB: %s", keyName);
wsprintfW(displayName, L"Raw Mouse %i", mouseCount++); dm->AddDevice(new RawInputKeyboard(list[i].hDevice, displayName, instanceID));
else }
wsprintfW(displayName, L"Raw MS: %s", keyName); else if (list[i].dwType == RIM_TYPEMOUSE)
dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID)); {
} if (!haveDescription)
} wsprintfW(displayName, L"Raw Mouse %i", mouseCount++);
} else
} wsprintfW(displayName, L"Raw MS: %s", keyName);
free(list); dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID));
free(instanceID); }
dm->AddDevice(new RawInputKeyboard(0, L"Simulated Keyboard")); }
dm->AddDevice(new RawInputMouse(0, L"Simulated Mouse")); }
} }
free(list);
free(instanceID);
dm->AddDevice(new RawInputKeyboard(0, L"Simulated Keyboard"));
dm->AddDevice(new RawInputMouse(0, L"Simulated Mouse"));
}
} }

View File

@ -17,112 +17,113 @@
#include "Global.h" #include "Global.h"
#include "resource_pad.h" #include "resource_pad.h"
LPWSTR dialog_message(int ID, bool *updateText) LPWSTR dialog_message(int ID, bool* updateText)
{ {
if (updateText) if (updateText)
*updateText = true; *updateText = true;
switch (ID) { switch (ID)
// General tab {
case IDC_M_WM: // General tab
case IDC_M_RAW: case IDC_M_WM:
case IDC_M_DI: case IDC_M_RAW:
return L"Enables mouse inputs to be used as pad controls.\n\n" case IDC_M_DI:
L"The mouse needs to be in focus to be used for playing. By default this is not the case as the \"Start without mouse focus\" checkbox is enabled. " return L"Enables mouse inputs to be used as pad controls.\n\n"
L"Either disable this checkbox or enable/disable the mouse while playing by assigning a key to the \"Mouse\" button on the Pad tabs.\n\n" L"The mouse needs to be in focus to be used for playing. By default this is not the case as the \"Start without mouse focus\" checkbox is enabled. "
L"Note 1: By default PCSX2 uses a double-click by the left mouse button to toggle fullscreen mode, this makes the left mouse button unusable as an input." L"Either disable this checkbox or enable/disable the mouse while playing by assigning a key to the \"Mouse\" button on the Pad tabs.\n\n"
L"To disable this option in PCSX2 go to Config > Emulation Settings > GS Window tab, and disable the \"Double-click toggles fullscreen mode\" checkbox.\n\n" L"Note 1: By default PCSX2 uses a double-click by the left mouse button to toggle fullscreen mode, this makes the left mouse button unusable as an input."
L"Note 2: This does not enable the mouse to function as an in-game mouse in PS2 games that support a USB mouse or lightgun." L"To disable this option in PCSX2 go to Config > Emulation Settings > GS Window tab, and disable the \"Double-click toggles fullscreen mode\" checkbox.\n\n"
L"This requires a USB plugin, while LilyPad is a PAD plugin(PAD means it emulates devices that are to be plugged into the PlayStation controller port that connects the DualShock 2 controller)."; L"Note 2: This does not enable the mouse to function as an in-game mouse in PS2 games that support a USB mouse or lightgun."
case IDC_MOUSE_UNFOCUS: L"This requires a USB plugin, while LilyPad is a PAD plugin(PAD means it emulates devices that are to be plugged into the PlayStation controller port that connects the DualShock 2 controller).";
return L"Enabled: Mouse is unfocused and can be used for emulation and outside it.\n\n" case IDC_MOUSE_UNFOCUS:
L"Disabled: Mouse is focused and can be used for emulation."; return L"Enabled: Mouse is unfocused and can be used for emulation and outside it.\n\n"
case IDC_MULTIPLE_BINDING: L"Disabled: Mouse is focused and can be used for emulation.";
return L"Allows binding multiple PS2 controls to one PC control, and binding conflicting controls on opposing ports and/or slots.\n\n" case IDC_MULTIPLE_BINDING:
L"Also enables swapping different kinds of pad types(for example, between DS2 and Guitar) when right-clicking in the pad list."; return L"Allows binding multiple PS2 controls to one PC control, and binding conflicting controls on opposing ports and/or slots.\n\n"
case IDC_PAD_LIST: L"Also enables swapping different kinds of pad types(for example, between DS2 and Guitar) when right-clicking in the pad list.";
return L"Left-click on one of the available pads to enable the pad specific options on the right." case IDC_PAD_LIST:
L"These options include being able to select the pad type(DS2, Guitar, etc.) and enabling automatic analog mode for PS1 emulation.\n\n" return L"Left-click on one of the available pads to enable the pad specific options on the right."
L"Right-click to show a pop-up menu that allows for swapping all the settings and bindings, or just the bindings of individual pad types," L"These options include being able to select the pad type(DS2, Guitar, etc.) and enabling automatic analog mode for PS1 emulation.\n\n"
L"between the selected pad and one of other active pads, and clearing all the settings and bindings from the selected pad or just the bindings from a selected pad type.\n\n" L"Right-click to show a pop-up menu that allows for swapping all the settings and bindings, or just the bindings of individual pad types,"
L"Note: To allow swapping different kinds of pad types(like DS2 to Guitar), the \"Allow binding multiple PS2 Controls...\" option needs to be enabled as well."; L"between the selected pad and one of other active pads, and clearing all the settings and bindings from the selected pad or just the bindings from a selected pad type.\n\n"
case IDC_PAD_TYPE: L"Note: To allow swapping different kinds of pad types(like DS2 to Guitar), the \"Allow binding multiple PS2 Controls...\" option needs to be enabled as well.";
return L"\"Unplugged\" disables the controller and removes the corresponding pad tab.\n\n" case IDC_PAD_TYPE:
L"\"Dualshock 2\" emulates the default PS2 controller for use in both PS1 and PS2 games.\n\n" return L"\"Unplugged\" disables the controller and removes the corresponding pad tab.\n\n"
L"\"Guitar\" emulates a PS2 controller used in the Guitar Hero and Rock Band series of games.\n\n" L"\"Dualshock 2\" emulates the default PS2 controller for use in both PS1 and PS2 games.\n\n"
L"\"Pop'n Music controller\" emulates a PS2 controller used exclusively in the Japanese Pop'n Music series of games.\n\n" L"\"Guitar\" emulates a PS2 controller used in the Guitar Hero and Rock Band series of games.\n\n"
L"\"PS1 Mouse\" emulates the PlayStation Mouse. This controller can only be used in a number of PS1 games like \"Command & Conquer: Red Alert\" and \"Myst\".\n\n" L"\"Pop'n Music controller\" emulates a PS2 controller used exclusively in the Japanese Pop'n Music series of games.\n\n"
L"\"neGcon\" emulates a controller that can be used in a number of PS1 games and PS2 games like the \"Ridge Racer\" and \"Ace Combat\" series."; L"\"PS1 Mouse\" emulates the PlayStation Mouse. This controller can only be used in a number of PS1 games like \"Command & Conquer: Red Alert\" and \"Myst\".\n\n"
case IDC_DIAG_LIST: L"\"neGcon\" emulates a controller that can be used in a number of PS1 games and PS2 games like the \"Ridge Racer\" and \"Ace Combat\" series.";
return L"Shows a list of currently available input devices.\n\n" case IDC_DIAG_LIST:
L"Double-click a device in the list or right-click it and select \"Test Device\" to display a continuously updated list of the state of all inputs on the selected device.\n" return L"Shows a list of currently available input devices.\n\n"
L"Use this option to check if all the inputs on a controller function properly.\n\n" L"Double-click a device in the list or right-click it and select \"Test Device\" to display a continuously updated list of the state of all inputs on the selected device.\n"
L"Right-click and select \"Refresh\" to update the list of devices in case a recently connected device has not shown up yet."; L"Use this option to check if all the inputs on a controller function properly.\n\n"
case IDC_G_DI: L"Right-click and select \"Refresh\" to update the list of devices in case a recently connected device has not shown up yet.";
return L"(Legacy) Enable this if your gamepad doesn't support Xinput.\n\n" case IDC_G_DI:
L"Disable for DualShock 4 (PS4 controllers) and probably others."; return L"(Legacy) Enable this if your gamepad doesn't support Xinput.\n\n"
case IDC_G_XI: L"Disable for DualShock 4 (PS4 controllers) and probably others.";
return L"For Xbox 360/ Xbox One controllers (or devices supporting Xinput).\n\n" case IDC_G_XI:
L"If it doesn't support Xinput then running through Steam as a non-Steam game might be required for the controllers to work properly.\n\n" return L"For Xbox 360/ Xbox One controllers (or devices supporting Xinput).\n\n"
L"https://gamepad-tester.com/ to test your controller and check if it only says 'Xinput' on top."; L"If it doesn't support Xinput then running through Steam as a non-Steam game might be required for the controllers to work properly.\n\n"
case ID_RESTORE_DEFAULTS: L"https://gamepad-tester.com/ to test your controller and check if it only says 'Xinput' on top.";
return L"Restores the default contents of LilyPad.ini, undoing all settings changes and bindings that have been set up."; case ID_RESTORE_DEFAULTS:
// Pad tabs return L"Restores the default contents of LilyPad.ini, undoing all settings changes and bindings that have been set up.";
case IDC_BINDINGS_LIST: // Pad tabs
return L"Shows a list of currently bound inputs of the selected Pad.\n\n" case IDC_BINDINGS_LIST:
L"Left-click on one of the bindings in the list to configure it.\n\n" return L"Shows a list of currently bound inputs of the selected Pad.\n\n"
L"Right-click and select \"Delete Selected\" to remove the selected input from the list.\n\n" L"Left-click on one of the bindings in the list to configure it.\n\n"
L"Right-click and select \"Clear All\" to remove all the inputs from the list.\n\n" L"Right-click and select \"Delete Selected\" to remove the selected input from the list.\n\n"
L"Note: Use Shift/Ctrl + Left-click to select multiple bindings. Changing the displayed configuration will now copy it to all selected bindings."; L"Right-click and select \"Clear All\" to remove all the inputs from the list.\n\n"
case IDC_DEVICE_SELECT: L"Note: Use Shift/Ctrl + Left-click to select multiple bindings. Changing the displayed configuration will now copy it to all selected bindings.";
return L"Select a single device to hide the bindings from other devices in the bindings list, and to only be able to add new bindings for the selected device.\n\n" case IDC_DEVICE_SELECT:
L"This can also avoid input conflict issues when one controller is recognized as several devices through different APIs."; return L"Select a single device to hide the bindings from other devices in the bindings list, and to only be able to add new bindings for the selected device.\n\n"
case IDC_CONFIGURE_ON_BIND: L"This can also avoid input conflict issues when one controller is recognized as several devices through different APIs.";
return L"Immediately go to the configuration setup when you create a new binding."; case IDC_CONFIGURE_ON_BIND:
case ID_MOUSE: return L"Immediately go to the configuration setup when you create a new binding.";
return L"Bind a key that releases or captures the mouse.\n\n" case ID_MOUSE:
L"Pressing the assigned button when the mouse is in focus, it releases the mouse from use in-game and makes the cursor visible so it can move/resize the emulator window.\n\n" return L"Bind a key that releases or captures the mouse.\n\n"
L"Alt-tabbing to another application also makes the cursor visible, but focusing the emulation window hides it again.\n\n" L"Pressing the assigned button when the mouse is in focus, it releases the mouse from use in-game and makes the cursor visible so it can move/resize the emulator window.\n\n"
L"Pressing the button when the mouse is out of focus and visible, it captures the mouse so that it can be used as a controller again.\n\n" L"Alt-tabbing to another application also makes the cursor visible, but focusing the emulation window hides it again.\n\n"
L"Note 1: Though the binding appears on the page of a specific pad, pressing the button affects all mice.\n\n" L"Pressing the button when the mouse is out of focus and visible, it captures the mouse so that it can be used as a controller again.\n\n"
L"Note 2: By default PCSX2 uses a double-click by the left mouse button to toggle fullscreen mode, this makes the left mouse button unusable as an input." L"Note 1: Though the binding appears on the page of a specific pad, pressing the button affects all mice.\n\n"
L"To disable this option in PCSX2 go to Config > Emulation Settings > GS Window tab, and disable the \"Double-click toggles fullscreen mode\" checkbox."; L"Note 2: By default PCSX2 uses a double-click by the left mouse button to toggle fullscreen mode, this makes the left mouse button unusable as an input."
case ID_ANALOG: L"To disable this option in PCSX2 go to Config > Emulation Settings > GS Window tab, and disable the \"Double-click toggles fullscreen mode\" checkbox.";
return L"Bind a keys that switches the pad from digital mode to analog mode and vice versa.\n\n" case ID_ANALOG:
L"This option is useful when analog mode is enabled in a game that does not support it, as this causes the game to not recognise any input or to not even detect a controller.\n\n" return L"Bind a keys that switches the pad from digital mode to analog mode and vice versa.\n\n"
L"This option can also be used to enable analog mode in games that support, but do not automatically enable analog mode.\n\n" L"This option is useful when analog mode is enabled in a game that does not support it, as this causes the game to not recognise any input or to not even detect a controller.\n\n"
L"Note: Analog mode enables the analog sticks to function on a DualShock controller, while in digital mode it behaves as an original PlayStation controller.\n\n"; L"This option can also be used to enable analog mode in games that support, but do not automatically enable analog mode.\n\n"
case ID_TURBO_KEY: L"Note: Analog mode enables the analog sticks to function on a DualShock controller, while in digital mode it behaves as an original PlayStation controller.\n\n";
return L"Sets a key to send a TAB press to the emulator, which toggles Turbo mode(200% speed) in PCSX2."; case ID_TURBO_KEY:
case ID_EXCLUDE: return L"Sets a key to send a TAB press to the emulator, which toggles Turbo mode(200% speed) in PCSX2.";
return L"Disables an input so it will be ignored when trying to bind another input.\n\n" case ID_EXCLUDE:
L"This is helpful when binding controls for a device with an input that's difficult to center like an accelerator, or just always active like a faulty button or analog stick."; return L"Disables an input so it will be ignored when trying to bind another input.\n\n"
case ID_LOCK_ALL_INPUT: L"This is helpful when binding controls for a device with an input that's difficult to center like an accelerator, or just always active like a faulty button or analog stick.";
return L"Locks the current state of the pad. Any further input is handled normally, but the initial pad state is the locked state instead of a state with no buttons pressed. " case ID_LOCK_ALL_INPUT:
L"Pressing it again releases the old pad state, if the old pad state had any keys pressed. Otherwise, it's released automatically."; return L"Locks the current state of the pad. Any further input is handled normally, but the initial pad state is the locked state instead of a state with no buttons pressed. "
case ID_LOCK_DIRECTION: L"Pressing it again releases the old pad state, if the old pad state had any keys pressed. Otherwise, it's released automatically.";
return L"Locks the current state of the d-pad and analog sticks. Pressing this when all input is locked unlocks only the pad and sticks." case ID_LOCK_DIRECTION:
L"Pressing it again will lock them again, keeping the buttons locked."; return L"Locks the current state of the d-pad and analog sticks. Pressing this when all input is locked unlocks only the pad and sticks."
case ID_LOCK_BUTTONS: L"Pressing it again will lock them again, keeping the buttons locked.";
return L"Locks the current state of the buttons. Pressing this when all input is locked unlocks only the buttons. " case ID_LOCK_BUTTONS:
L"Pressing it again will lock them again, keeping the d-pad and analog sticks locked."; return L"Locks the current state of the buttons. Pressing this when all input is locked unlocks only the buttons. "
case IDC_RAPID_FIRE: L"Pressing it again will lock them again, keeping the d-pad and analog sticks locked.";
return L"Automatically presses/releases the input every other time the button is polled."; case IDC_RAPID_FIRE:
case IDC_FLIP: return L"Automatically presses/releases the input every other time the button is polled.";
return L"Inverts a button or axis, making down up and up down."; case IDC_FLIP:
case IDC_SLIDER_DEADZONE: return L"Inverts a button or axis, making down up and up down.";
return L"Decreases or increases the range of an input where no input is recognised.\n\n" case IDC_SLIDER_DEADZONE:
L"Increasing the dead zone requires the input to be pressed harder or moved more before it is applied, decreasing it makes it recognise a softer press or a shorter movement."; return L"Decreases or increases the range of an input where no input is recognised.\n\n"
case IDC_SLIDER_SKIP_DEADZONE: L"Increasing the dead zone requires the input to be pressed harder or moved more before it is applied, decreasing it makes it recognise a softer press or a shorter movement.";
return L"Skips and avoids the dead zone to detect input earlier.\n\n" case IDC_SLIDER_SKIP_DEADZONE:
L"Note: This is useful when a controller input requires too much movement/pressure before there's a corresponding action in-game."; return L"Skips and avoids the dead zone to detect input earlier.\n\n"
case IDC_SLIDER_SENSITIVITY: L"Note: This is useful when a controller input requires too much movement/pressure before there's a corresponding action in-game.";
return L"Sets how hard an axis or button is pressed.\n\n" case IDC_SLIDER_SENSITIVITY:
L"Note 1: What the default sensitivity value of \"1.00\" means depends on the device itself. The default is high enough that relative axes (which are primarily used by mice) are generally either considered fully up or down." return L"Sets how hard an axis or button is pressed.\n\n"
L"For absolute axes (and force feedback devices), which are used by most game devices, a value of 1.0 should map the device's extreme values to the extreme values of a stick/pad.\n\n" L"Note 1: What the default sensitivity value of \"1.00\" means depends on the device itself. The default is high enough that relative axes (which are primarily used by mice) are generally either considered fully up or down."
L"Note 2: Setting the sensitivity of PC button bindings only really has an effect for PS2 analog sticks or when playing a game with full DS2 pressure sensitivity support."; L"For absolute axes (and force feedback devices), which are used by most game devices, a value of 1.0 should map the device's extreme values to the extreme values of a stick/pad.\n\n"
default: L"Note 2: Setting the sensitivity of PC button bindings only really has an effect for PS2 analog sticks or when playing a game with full DS2 pressure sensitivity support.";
if (updateText) default:
*updateText = false; if (updateText)
return L""; *updateText = false;
} return L"";
}
} }

View File

@ -18,6 +18,6 @@
#include "Global.h" #include "Global.h"
LPWSTR dialog_message(int ID, bool *updateText = false); LPWSTR dialog_message(int ID, bool* updateText = false);
#endif #endif

View File

@ -17,91 +17,95 @@
#include "Global.h" #include "Global.h"
#include "VKey.h" #include "VKey.h"
wchar_t *GetVKStringW(unsigned char vk) wchar_t* GetVKStringW(unsigned char vk)
{ {
int flag; int flag;
static wchar_t t[20]; static wchar_t t[20];
switch (vk) { switch (vk)
case 0x0C: {
return L"Clear"; case 0x0C:
case 0x13: return L"Clear";
return L"Pause"; case 0x13:
return L"Pause";
case 0x21: // return "Page Up"; case 0x21: // return "Page Up";
case 0x22: // return "Page Down"; case 0x22: // return "Page Down";
case 0x23: // return "End"; case 0x23: // return "End";
case 0x24: // return "Home"; case 0x24: // return "Home";
case 0x25: // return "Left"; case 0x25: // return "Left";
case 0x26: // return "Up"; case 0x26: // return "Up";
case 0x27: // return "Right"; case 0x27: // return "Right";
case 0x28: // return "Down"; case 0x28: // return "Down";
case 0x2D: // return "Insert"; case 0x2D: // return "Insert";
case 0x2E: // return "Delete"; case 0x2E: // return "Delete";
case 0x5B: // return "Left Windows"; case 0x5B: // return "Left Windows";
case 0x5C: // return "Right Windows"; case 0x5C: // return "Right Windows";
case 0x5D: // return "Application"; case 0x5D: // return "Application";
case 0x6F: // return "Num /"; case 0x6F: // return "Num /";
flag = 1 << 24; flag = 1 << 24;
break; break;
case 0x29: case 0x29:
return L"Select"; return L"Select";
case 0x2A: case 0x2A:
return L"Print"; return L"Print";
case 0x2B: case 0x2B:
return L"Execute"; return L"Execute";
case 0x2C: case 0x2C:
return L"Prnt Scrn"; return L"Prnt Scrn";
case 0x2F: case 0x2F:
return L"Help"; return L"Help";
case 0x6C: case 0x6C:
return L"|"; return L"|";
case 0x90: case 0x90:
return L"Num Lock"; return L"Num Lock";
case 0xA0: case 0xA0:
return L"Left Shift"; return L"Left Shift";
case 0xA1: case 0xA1:
return L"Right Shift"; return L"Right Shift";
case 0xA2: case 0xA2:
return L"Left Ctrl"; return L"Left Ctrl";
case 0xA3: case 0xA3:
return L"Right Ctrl"; return L"Right Ctrl";
case 0xA4: case 0xA4:
return L"Left Alt"; return L"Left Alt";
case 0xA5: case 0xA5:
return L"Right Alt"; return L"Right Alt";
case 0xA6: case 0xA6:
return L"Back"; return L"Back";
case 0xA7: case 0xA7:
return L"Forward"; return L"Forward";
case 0xA8: case 0xA8:
return L"Refresh"; return L"Refresh";
case 0xA9: case 0xA9:
return L"Stop"; return L"Stop";
case 0xAA: case 0xAA:
return L"Search"; return L"Search";
case 0xAB: case 0xAB:
return L"Favorites"; return L"Favorites";
case 0xAC: case 0xAC:
return L"Browser"; return L"Browser";
case 0xFA: case 0xFA:
return L"Play"; return L"Play";
case 0xFB: case 0xFB:
return L"Zoom"; return L"Zoom";
default: default:
flag = 0; flag = 0;
break; break;
} }
int res = MapVirtualKey(vk, MAPVK_VK_TO_VSC); 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; // don't trust windows
} else { t[19] = 0;
wsprintfW(t, L"Key %i", vk); }
} else
return t; {
wsprintfW(t, L"Key %i", vk);
}
return t;
} }

View File

@ -14,4 +14,4 @@
*/ */
// Maps virtual key codes to strings. // Maps virtual key codes to strings.
wchar_t *GetVKStringW(unsigned char vk); wchar_t* GetVKStringW(unsigned char vk);

View File

@ -20,51 +20,58 @@
#include "WindowsKeyboard.h" #include "WindowsKeyboard.h"
#include "KeyboardQueue.h" #include "KeyboardQueue.h"
WindowsKeyboard::WindowsKeyboard(DeviceAPI api, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID) WindowsKeyboard::WindowsKeyboard(DeviceAPI api, wchar_t* displayName, wchar_t* instanceID, wchar_t* deviceID)
: Device(api, KEYBOARD, displayName, instanceID, deviceID) : Device(api, KEYBOARD, displayName, instanceID, deviceID)
{ {
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++)
AddPhysicalControl(PSHBTN, i, i); {
} AddPhysicalControl(PSHBTN, i, i);
}
} }
wchar_t *WindowsKeyboard::GetPhysicalControlName(PhysicalControl *control) wchar_t* WindowsKeyboard::GetPhysicalControlName(PhysicalControl* control)
{ {
int id = control->id; int id = control->id;
if (control->type == PSHBTN && id >= 0 && id < 256) { if (control->type == PSHBTN && id >= 0 && id < 256)
wchar_t *w = GetVKStringW(id); {
if (w) wchar_t* w = GetVKStringW(id);
return w; if (w)
} return w;
return Device::GetPhysicalControlName(control); }
return Device::GetPhysicalControlName(control);
} }
void WindowsKeyboard::UpdateKey(int vkey, int state) void WindowsKeyboard::UpdateKey(int vkey, int state)
{ {
if (vkey > 7 && vkey < 256) { if (vkey > 7 && vkey < 256)
int newState = state * FULLY_DOWN; {
if (newState != physicalControlState[vkey]) { int newState = state * FULLY_DOWN;
// Check for alt-F4 to avoid toggling skip mode incorrectly. if (newState != physicalControlState[vkey])
if (vkey != VK_F4 || !(physicalControlState[VK_MENU] || physicalControlState[VK_RMENU] || physicalControlState[VK_LMENU])) { {
int event = KEYPRESS; // Check for alt-F4 to avoid toggling skip mode incorrectly.
if (!newState) if (vkey != VK_F4 || !(physicalControlState[VK_MENU] || physicalControlState[VK_RMENU] || physicalControlState[VK_LMENU]))
event = KEYRELEASE; {
QueueKeyEvent(vkey, event); int event = KEYPRESS;
} if (!newState)
} event = KEYRELEASE;
physicalControlState[vkey] = newState; QueueKeyEvent(vkey, event);
} }
}
physicalControlState[vkey] = newState;
}
} }
void WindowsKeyboard::InitState() void WindowsKeyboard::InitState()
{ {
AllocState(); AllocState();
for (int vkey = 5; vkey < 256; vkey++) { for (int vkey = 5; vkey < 256; vkey++)
int value = (unsigned short)(((short)GetAsyncKeyState(vkey)) >> 15); {
value += value & 1; int value = (unsigned short)(((short)GetAsyncKeyState(vkey)) >> 15);
if (vkey == VK_CONTROL || vkey == VK_MENU || vkey == VK_SHIFT) { value += value & 1;
value = 0; if (vkey == VK_CONTROL || vkey == VK_MENU || vkey == VK_SHIFT)
} {
physicalControlState[vkey] = value; value = 0;
} }
physicalControlState[vkey] = value;
}
} }

View File

@ -17,10 +17,10 @@
class WindowsKeyboard : public Device class WindowsKeyboard : public Device
{ {
public: 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); wchar_t* GetPhysicalControlName(PhysicalControl* control);
void UpdateKey(int vkey, int state); void UpdateKey(int vkey, int state);
// Calls AllocState() and initializes to current keyboard state using // Calls AllocState() and initializes to current keyboard state using
// GetAsyncKeyState(). // GetAsyncKeyState().
void InitState(); void InitState();
}; };

View File

@ -23,170 +23,200 @@
#include "WindowsKeyboard.h" #include "WindowsKeyboard.h"
#include "WindowsMouse.h" #include "WindowsMouse.h"
ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output); ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* output);
class WindowsMessagingKeyboard; class WindowsMessagingKeyboard;
class WindowsMessagingMouse; class WindowsMessagingMouse;
static WindowsMessagingKeyboard *wmk = 0; static WindowsMessagingKeyboard* wmk = 0;
static WindowsMessagingMouse *wmm = 0; static WindowsMessagingMouse* wmm = 0;
class WindowsMessagingKeyboard : public WindowsKeyboard class WindowsMessagingKeyboard : public WindowsKeyboard
{ {
public: public:
WindowsMessagingKeyboard() WindowsMessagingKeyboard()
: WindowsKeyboard(WM, L"WM Keyboard") : WindowsKeyboard(WM, L"WM Keyboard")
{ {
} }
int Activate(InitInfo *initInfo) int Activate(InitInfo* initInfo)
{ {
// Redundant. Should match the next line. // Redundant. Should match the next line.
// Deactivate(); // Deactivate();
if (wmk) if (wmk)
wmk->Deactivate(); wmk->Deactivate();
hWndProc = initInfo->hWndProc; hWndProc = initInfo->hWndProc;
if (!wmm) if (!wmm)
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES); hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
wmk = this; wmk = this;
InitState(); InitState();
active = 1; active = 1;
return 1; return 1;
} }
void Deactivate() void Deactivate()
{ {
if (active) { if (active)
if (!wmm) {
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc); if (!wmm)
wmk = 0; hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
active = 0; wmk = 0;
FreeState(); active = 0;
} FreeState();
} }
}
void CheckKey(int vkey) void CheckKey(int vkey)
{ {
UpdateKey(vkey, 1 & (((unsigned short)GetAsyncKeyState(vkey)) >> 15)); UpdateKey(vkey, 1 & (((unsigned short)GetAsyncKeyState(vkey)) >> 15));
} }
}; };
class WindowsMessagingMouse : public WindowsMouse class WindowsMessagingMouse : public WindowsMouse
{ {
public: public:
WindowsMessagingMouse() WindowsMessagingMouse()
: WindowsMouse(WM, 1, L"WM Mouse") : WindowsMouse(WM, 1, L"WM Mouse")
{ {
} }
int Activate(InitInfo *initInfo) int Activate(InitInfo* initInfo)
{ {
// Redundant. Should match the next line. // Redundant. Should match the next line.
// Deactivate(); // Deactivate();
if (wmm) if (wmm)
wmm->Deactivate(); wmm->Deactivate();
hWndProc = initInfo->hWndProc; hWndProc = initInfo->hWndProc;
if (!wmk) if (!wmk)
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES); hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
GetMouseCapture(hWndProc->hWndEaten); GetMouseCapture(hWndProc->hWndEaten);
active = 1; active = 1;
wmm = this; wmm = this;
AllocState(); AllocState();
return 1; return 1;
} }
void Deactivate() void Deactivate()
{ {
if (active) { if (active)
if (!wmk) {
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc); if (!wmk)
ReleaseMouseCapture(); hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
wmm = 0; ReleaseMouseCapture();
active = 0; wmm = 0;
FreeState(); active = 0;
} FreeState();
} }
}
}; };
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 (wmk)
if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN || uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP) { {
if (wParam == VK_SHIFT) { if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN || uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP)
wmk->CheckKey(VK_RSHIFT); {
wmk->CheckKey(VK_LSHIFT); if (wParam == VK_SHIFT)
} else if (wParam == VK_CONTROL) { {
wmk->CheckKey(VK_RCONTROL); wmk->CheckKey(VK_RSHIFT);
wmk->CheckKey(VK_LCONTROL); wmk->CheckKey(VK_LSHIFT);
} else if (wParam == VK_MENU) { }
wmk->CheckKey(VK_RMENU); else if (wParam == VK_CONTROL)
wmk->CheckKey(VK_LMENU); {
} else wmk->CheckKey(VK_RCONTROL);
wmk->UpdateKey(wParam, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)); wmk->CheckKey(VK_LCONTROL);
return NO_WND_PROC; }
} else if (wParam == VK_MENU)
// Needed to prevent default handling of keys in some situations. {
else if (uMsg == WM_CHAR || uMsg == WM_UNICHAR) { wmk->CheckKey(VK_RMENU);
return NO_WND_PROC; wmk->CheckKey(VK_LMENU);
} else if (uMsg == WM_ACTIVATE) { }
// Not really needed, but doesn't hurt. else
memset(wmk->physicalControlState, 0, sizeof(int) * wmk->numPhysicalControls); wmk->UpdateKey(wParam, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN));
} return NO_WND_PROC;
} }
if (wmm) { // Needed to prevent default handling of keys in some situations.
if (uMsg == WM_MOUSEMOVE) { else if (uMsg == WM_CHAR || uMsg == WM_UNICHAR)
POINT p; {
GetCursorPos(&p); return NO_WND_PROC;
// Need check to prevent cursor movement cascade. }
if (p.x != wmm->center.x || p.y != wmm->center.y) { else if (uMsg == WM_ACTIVATE)
wmm->UpdateAxis(0, p.x - wmm->center.x); {
wmm->UpdateAxis(1, p.y - wmm->center.y); // Not really needed, but doesn't hurt.
memset(wmk->physicalControlState, 0, sizeof(int) * wmk->numPhysicalControls);
}
}
if (wmm)
{
if (uMsg == WM_MOUSEMOVE)
{
POINT p;
GetCursorPos(&p);
// Need check to prevent cursor movement cascade.
if (p.x != wmm->center.x || p.y != wmm->center.y)
{
wmm->UpdateAxis(0, p.x - wmm->center.x);
wmm->UpdateAxis(1, p.y - wmm->center.y);
SetCursorPos(wmm->center.x, wmm->center.y); SetCursorPos(wmm->center.x, wmm->center.y);
} }
return NO_WND_PROC; return NO_WND_PROC;
} else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) { }
wmm->UpdateButton(0, uMsg == WM_LBUTTONDOWN); else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
return NO_WND_PROC; {
} else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) { wmm->UpdateButton(0, uMsg == WM_LBUTTONDOWN);
wmm->UpdateButton(1, uMsg == WM_RBUTTONDOWN); return NO_WND_PROC;
return NO_WND_PROC; }
} else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) { else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP)
wmm->UpdateButton(2, uMsg == WM_MBUTTONDOWN); {
return NO_WND_PROC; wmm->UpdateButton(1, uMsg == WM_RBUTTONDOWN);
} else if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) { return NO_WND_PROC;
wmm->UpdateButton(3 + ((wParam >> 16) == XBUTTON2), uMsg == WM_XBUTTONDOWN); }
return NO_WND_PROC; else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)
} else if (uMsg == WM_MOUSEWHEEL) { {
wmm->UpdateAxis(2, ((int)wParam >> 16) / WHEEL_DELTA); wmm->UpdateButton(2, uMsg == WM_MBUTTONDOWN);
return NO_WND_PROC; return NO_WND_PROC;
} else if (uMsg == WM_MOUSEHWHEEL) { }
wmm->UpdateAxis(3, ((int)wParam >> 16) / WHEEL_DELTA); else if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)
return NO_WND_PROC; {
} else if (uMsg == WM_SIZE && wmm->active) { wmm->UpdateButton(3 + ((wParam >> 16) == XBUTTON2), uMsg == WM_XBUTTONDOWN);
WindowsMouse::WindowResized(hWnd); return NO_WND_PROC;
} }
// Taken care of elsewhere. When binding, killing focus means stop reading input. else if (uMsg == WM_MOUSEWHEEL)
// When running PCSX2, I release all mouse and keyboard input elsewhere. {
/*else if (uMsg == WM_KILLFOCUS) { 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);
return NO_WND_PROC;
}
else if (uMsg == WM_SIZE && wmm->active)
{
WindowsMouse::WindowResized(hWnd);
}
// Taken care of elsewhere. When binding, killing focus means stop reading input.
// When running PCSX2, I release all mouse and keyboard input elsewhere.
/*else if (uMsg == WM_KILLFOCUS) {
wmm->Deactivate(); wmm->Deactivate();
}//*/ }//*/
} }
return CONTINUE_BLISSFULLY; return CONTINUE_BLISSFULLY;
} }
void EnumWindowsMessagingDevices() void EnumWindowsMessagingDevices()
{ {
dm->AddDevice(new WindowsMessagingKeyboard()); dm->AddDevice(new WindowsMessagingKeyboard());
dm->AddDevice(new WindowsMessagingMouse()); dm->AddDevice(new WindowsMessagingMouse());
} }

View File

@ -22,80 +22,82 @@
POINT WindowsMouse::origCursorPos; POINT WindowsMouse::origCursorPos;
POINT WindowsMouse::center; POINT WindowsMouse::center;
WindowsMouse::WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID) WindowsMouse::WindowsMouse(DeviceAPI api, int hWheel, wchar_t* displayName, wchar_t* instanceID, wchar_t* deviceID)
: Device(api, MOUSE, displayName, instanceID, deviceID) : Device(api, MOUSE, displayName, instanceID, deviceID)
{ {
int i; int i;
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++)
AddPhysicalControl(PSHBTN, i, i); {
} AddPhysicalControl(PSHBTN, i, i);
}
for (i = 0; i < 3 + hWheel; i++) { for (i = 0; i < 3 + hWheel; i++)
AddPhysicalControl(RELAXIS, i + 5, i + 5); {
} AddPhysicalControl(RELAXIS, i + 5, i + 5);
}
} }
wchar_t *WindowsMouse::GetPhysicalControlName(PhysicalControl *control) wchar_t* WindowsMouse::GetPhysicalControlName(PhysicalControl* control)
{ {
wchar_t *names[9] = { wchar_t* names[9] = {
L"L Button", L"L Button",
L"R Button", L"R Button",
L"M Button", L"M Button",
L"Mouse 4", L"Mouse 4",
L"Mouse 5", L"Mouse 5",
L"X Axis", L"X Axis",
L"Y Axis", L"Y Axis",
L"Y Wheel", L"Y Wheel",
L"X Wheel"}; L"X Wheel"};
if (control->id < 9) if (control->id < 9)
return names[control->id]; return names[control->id];
return Device::GetPhysicalControlName(control); return Device::GetPhysicalControlName(control);
} }
void WindowsMouse::UpdateButton(unsigned int button, int state) void WindowsMouse::UpdateButton(unsigned int button, int state)
{ {
if (button > 4) if (button > 4)
return; return;
physicalControlState[button] = (state << 16); physicalControlState[button] = (state << 16);
} }
void WindowsMouse::UpdateAxis(unsigned int axis, int delta) void WindowsMouse::UpdateAxis(unsigned int axis, int delta)
{ {
if (axis > 3) if (axis > 3)
return; return;
// 1 mouse pixel = 1/8th way down. // 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; RECT r;
GetWindowRect(hWnd, &r); GetWindowRect(hWnd, &r);
ClipCursor(&r); ClipCursor(&r);
center.x = (r.left + r.right) / 2; center.x = (r.left + r.right) / 2;
center.y = (r.top + r.bottom) / 2; center.y = (r.top + r.bottom) / 2;
SetCursorPos(center.x, center.y); SetCursorPos(center.x, center.y);
} }
void WindowsMouse::GetMouseCapture(HWND hWnd) void WindowsMouse::GetMouseCapture(HWND hWnd)
{ {
SetCapture(hWnd); SetCapture(hWnd);
ShowCursor(0); ShowCursor(0);
GetCursorPos(&origCursorPos); GetCursorPos(&origCursorPos);
RECT r; RECT r;
GetWindowRect(hWnd, &r); GetWindowRect(hWnd, &r);
ClipCursor(&r); ClipCursor(&r);
center.x = (r.left + r.right) / 2; center.x = (r.left + r.right) / 2;
center.y = (r.top + r.bottom) / 2; center.y = (r.top + r.bottom) / 2;
SetCursorPos(center.x, center.y); SetCursorPos(center.x, center.y);
} }
void WindowsMouse::ReleaseMouseCapture() void WindowsMouse::ReleaseMouseCapture()
{ {
ClipCursor(0); ClipCursor(0);
ReleaseCapture(); ReleaseCapture();
ShowCursor(1); ShowCursor(1);
SetCursorPos(origCursorPos.x, origCursorPos.y); SetCursorPos(origCursorPos.x, origCursorPos.y);
} }

View File

@ -17,24 +17,24 @@
class WindowsMouse : public Device class WindowsMouse : public Device
{ {
public: public:
// Used by GetMouseCapture()/ReleaseMouseCapture() // Used by GetMouseCapture()/ReleaseMouseCapture()
// Static because can have multiple raw mice active at once, // Static because can have multiple raw mice active at once,
// and only get/release capture once. // and only get/release capture once.
static POINT origCursorPos; static POINT origCursorPos;
static POINT center; static POINT center;
static void GetMouseCapture(HWND hWnd); static void GetMouseCapture(HWND hWnd);
static void WindowResized(HWND hWnd); static void WindowResized(HWND hWnd);
static void ReleaseMouseCapture(); static void ReleaseMouseCapture();
// hWheel variable lets me display no horizontal wheel for raw input, just to make it clear // hWheel variable lets me display no horizontal wheel for raw input, just to make it clear
// that it's not supported. // 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); wchar_t* GetPhysicalControlName(PhysicalControl* control);
// State is 0 for up, 1 for down. // State is 0 for up, 1 for down.
void UpdateButton(unsigned int button, int state); void UpdateButton(unsigned int button, int state);
// 0/1 are x/y. 2 is vert wheel, 3 is horiz wheel. // 0/1 are x/y. 2 is vert wheel, 3 is horiz wheel.
// Delta is in my micro units. change of (1<<16) is 1 full unit, with // Delta is in my micro units. change of (1<<16) is 1 full unit, with
// the default sensitivity. // the default sensitivity.
void UpdateAxis(unsigned int axis, int delta); void UpdateAxis(unsigned int axis, int delta);
}; };

View File

@ -19,136 +19,148 @@
WndProcEater::WndProcEater() WndProcEater::WndProcEater()
{ {
hWndEaten = 0; hWndEaten = 0;
eatenWndProc = 0; eatenWndProc = 0;
extraProcs = 0; extraProcs = 0;
numExtraProcs = 0; numExtraProcs = 0;
hMutex = CreateMutex(0, 0, L"LilyPad"); hMutex = CreateMutex(0, 0, L"LilyPad");
} }
WndProcEater::~WndProcEater() throw() WndProcEater::~WndProcEater() throw()
{ {
if (hMutex) { if (hMutex)
ReleaseMutex(hMutex); {
CloseHandle(hMutex); ReleaseMutex(hMutex);
} CloseHandle(hMutex);
}
} }
void WndProcEater::ReleaseExtraProc(ExtraWndProc proc) void WndProcEater::ReleaseExtraProc(ExtraWndProc proc)
{ {
// Probably isn't needed, but just in case... // Probably isn't needed, but just in case...
if (hMutex) if (hMutex)
WaitForSingleObject(hMutex, 100); WaitForSingleObject(hMutex, 100);
//printf( "(Lilypad) Regurgitating! -> 0x%x\n", proc ); //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]; if (extraProcs[i].proc == proc)
break; {
} extraProcs[i] = extraProcs[--numExtraProcs];
} break;
if (!numExtraProcs && eatenWndProc) { }
free(extraProcs); }
extraProcs = 0; if (!numExtraProcs && eatenWndProc)
// As numExtraProcs is 0, won't cause recursion if called from Release(). {
Release(); free(extraProcs);
} extraProcs = 0;
// As numExtraProcs is 0, won't cause recursion if called from Release().
Release();
}
} }
void WndProcEater::Release() void WndProcEater::Release()
{ {
while (numExtraProcs) while (numExtraProcs)
ReleaseExtraProc(extraProcs[0].proc); ReleaseExtraProc(extraProcs[0].proc);
if (hWndEaten && IsWindow(hWndEaten)) { if (hWndEaten && IsWindow(hWndEaten))
RemoveProp(hWndEaten, L"LilyHaxxor"); {
SetWindowLongPtr(hWndEaten, GWLP_WNDPROC, (LONG_PTR)eatenWndProc); RemoveProp(hWndEaten, L"LilyHaxxor");
hWndEaten = 0; SetWindowLongPtr(hWndEaten, GWLP_WNDPROC, (LONG_PTR)eatenWndProc);
eatenWndProc = 0; hWndEaten = 0;
} eatenWndProc = 0;
}
} }
LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
if (hWnd != hWndEaten) if (hWnd != hWndEaten)
fprintf(stderr, "Totally mismatched window handles on OverrideWndProc!\n"); fprintf(stderr, "Totally mismatched window handles on OverrideWndProc!\n");
ExtraWndProcResult res = CONTINUE_BLISSFULLY; ExtraWndProcResult res = CONTINUE_BLISSFULLY;
LRESULT out = 0; LRESULT out = 0;
// Here because want it for binding, even when no keyboard mode is selected. // Here because want it for binding, even when no keyboard mode is selected.
if (uMsg == WM_GETDLGCODE) { if (uMsg == WM_GETDLGCODE)
return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam); {
} 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 // Note: Second bit of deviceUpdateQueued is only set when I receive a device change
// is all I need to prevent bad things from happening while updating devices. No mutex needed. // notification, which is handled in the GS thread in one of the extraProcs, so this
// if ((deviceUpdateQueued&2) && (extraProcs[i].flags & EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) continue; // is all I need to prevent bad things from happening while updating devices. No mutex needed.
// if ((deviceUpdateQueued&2) && (extraProcs[i].flags & EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) continue;
ExtraWndProcResult res2 = extraProcs[i].proc(hWnd, uMsg, wParam, lParam, &out); ExtraWndProcResult res2 = extraProcs[i].proc(hWnd, uMsg, wParam, lParam, &out);
if (res2 != res) { if (res2 != res)
if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) { {
ReleaseExtraProc(extraProcs[i].proc); if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC)
i--; {
} else if (res2 > res) ReleaseExtraProc(extraProcs[i].proc);
res = res2; i--;
} }
} else if (res2 > res)
res = res2;
}
}
if (res != NO_WND_PROC) { if (res != NO_WND_PROC)
if (out == WM_DESTROY) { {
Release(); if (out == WM_DESTROY)
} {
if (res == CONTINUE_BLISSFULLY) Release();
out = CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam); }
else if (res == USE_DEFAULT_WND_PROC) if (res == CONTINUE_BLISSFULLY)
out = DefWindowProc(hWnd, uMsg, wParam, lParam); out = CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
} else if (res == USE_DEFAULT_WND_PROC)
return out; out = DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return out;
} }
static LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 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) ? return (obj == NULL) ?
DefWindowProc(hWnd, uMsg, wParam, lParam) : DefWindowProc(hWnd, uMsg, wParam, lParam) :
obj->_OverrideWndProc(hWnd, uMsg, wParam, lParam); obj->_OverrideWndProc(hWnd, uMsg, wParam, lParam);
} }
bool WndProcEater::SetWndHandle(HWND hWnd) bool WndProcEater::SetWndHandle(HWND hWnd)
{ {
if (hWnd == hWndEaten) if (hWnd == hWndEaten)
return true; return true;
//printf( "(Lilypad) (Re)-Setting window handle! -> this=0x%08x, hWnd=0x%08x\n", this, hWnd ); //printf( "(Lilypad) (Re)-Setting window handle! -> this=0x%08x, hWnd=0x%08x\n", this, hWnd );
Release(); 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; hWndEaten = (eatenWndProc) ? hWnd : 0;
return !!hWndEaten; return !!hWndEaten;
} }
void WndProcEater::Eat(ExtraWndProc proc, DWORD flags) void WndProcEater::Eat(ExtraWndProc proc, DWORD flags)
{ {
// check if Subclassing failed to init during SetWndHandle // check if Subclassing failed to init during SetWndHandle
if (!hWndEaten) if (!hWndEaten)
return; return;
// Probably isn't needed, but just in case... // Probably isn't needed, but just in case...
if (hMutex) if (hMutex)
WaitForSingleObject(hMutex, 100); WaitForSingleObject(hMutex, 100);
//printf( "(Lilypad) EatingWndProc! -> 0x%x\n", proc ); //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].proc = proc;
extraProcs[numExtraProcs].flags = flags; extraProcs[numExtraProcs].flags = flags;
numExtraProcs++; numExtraProcs++;
} }

View File

@ -17,42 +17,43 @@
/* Need this to let window be subclassed multiple times but still clean up nicely. /* Need this to let window be subclassed multiple times but still clean up nicely.
*/ */
enum ExtraWndProcResult { enum ExtraWndProcResult
CONTINUE_BLISSFULLY, {
// Calls ReleaseExtraProc without messing up order. CONTINUE_BLISSFULLY,
CONTINUE_BLISSFULLY_AND_RELEASE_PROC, // Calls ReleaseExtraProc without messing up order.
USE_DEFAULT_WND_PROC, CONTINUE_BLISSFULLY_AND_RELEASE_PROC,
NO_WND_PROC USE_DEFAULT_WND_PROC,
NO_WND_PROC
}; };
typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *out); typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* out);
struct ExtraWndProcInfo struct ExtraWndProcInfo
{ {
ExtraWndProc proc; ExtraWndProc proc;
DWORD flags; DWORD flags;
}; };
class WndProcEater class WndProcEater
{ {
public: public:
HWND hWndEaten; HWND hWndEaten;
WNDPROC eatenWndProc; WNDPROC eatenWndProc;
ExtraWndProcInfo *extraProcs; ExtraWndProcInfo* extraProcs;
int numExtraProcs; int numExtraProcs;
HANDLE hMutex; HANDLE hMutex;
public: public:
WndProcEater(); WndProcEater();
virtual ~WndProcEater() throw(); virtual ~WndProcEater() throw();
bool SetWndHandle(HWND hWnd); bool SetWndHandle(HWND hWnd);
void Eat(ExtraWndProc proc, DWORD flags); void Eat(ExtraWndProc proc, DWORD flags);
void ReleaseExtraProc(ExtraWndProc proc); void ReleaseExtraProc(ExtraWndProc proc);
void Release(); void Release();
LRESULT _OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT _OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
}; };
extern WndProcEater hWndGSProc; extern WndProcEater hWndGSProc;

View File

@ -27,43 +27,43 @@
typedef struct typedef struct
{ {
float SCP_UP; float SCP_UP;
float SCP_RIGHT; float SCP_RIGHT;
float SCP_DOWN; float SCP_DOWN;
float SCP_LEFT; float SCP_LEFT;
float SCP_LX; float SCP_LX;
float SCP_LY; float SCP_LY;
float SCP_L1; float SCP_L1;
float SCP_L2; float SCP_L2;
float SCP_L3; float SCP_L3;
float SCP_RX; float SCP_RX;
float SCP_RY; float SCP_RY;
float SCP_R1; float SCP_R1;
float SCP_R2; float SCP_R2;
float SCP_R3; float SCP_R3;
float SCP_T; float SCP_T;
float SCP_C; float SCP_C;
float SCP_X; float SCP_X;
float SCP_S; float SCP_S;
float SCP_SELECT; float SCP_SELECT;
float SCP_START; float SCP_START;
float SCP_PS; float SCP_PS;
} SCP_EXTN; } SCP_EXTN;
// This way, I don't require that XInput junk be installed. // This way, I don't require that XInput junk be installed.
typedef void(CALLBACK *_XInputEnable)(BOOL enable); typedef void(CALLBACK* _XInputEnable)(BOOL enable);
typedef DWORD(CALLBACK *_XInputGetStateEx)(DWORD dwUserIndex, XINPUT_STATE *pState); typedef DWORD(CALLBACK* _XInputGetStateEx)(DWORD dwUserIndex, XINPUT_STATE* pState);
typedef DWORD(CALLBACK *_XInputGetExtended)(DWORD dwUserIndex, SCP_EXTN *pPressure); typedef DWORD(CALLBACK* _XInputGetExtended)(DWORD dwUserIndex, SCP_EXTN* pPressure);
typedef DWORD(CALLBACK *_XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration); typedef DWORD(CALLBACK* _XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
_XInputEnable pXInputEnable = 0; _XInputEnable pXInputEnable = 0;
_XInputGetStateEx pXInputGetStateEx = 0; _XInputGetStateEx pXInputGetStateEx = 0;
@ -76,229 +76,253 @@ static int xInputActiveCount = 0;
// Completely unncessary, really. // Completely unncessary, really.
__forceinline int ShortToAxis(int v) __forceinline int ShortToAxis(int v)
{ {
// If positive and at least 1 << 14, increment. // If positive and at least 1 << 14, increment.
v += (!((v >> 15) & 1)) & ((v >> 14) & 1); v += (!((v >> 15) & 1)) & ((v >> 14) & 1);
// Just double. // Just double.
return v * 2; return v * 2;
} }
class XInputDevice : public Device class XInputDevice : public Device
{ {
// Cached last vibration values by pad and motor. // Cached last vibration values by pad and motor.
// Need this, as only one value is changed at a time. // Need this, as only one value is changed at a time.
int ps2Vibration[2][4][2]; int ps2Vibration[2][4][2];
// Minor optimization - cache last set vibration values // Minor optimization - cache last set vibration values
// When there's no change, no need to do anything. // When there's no change, no need to do anything.
XINPUT_VIBRATION xInputVibration; XINPUT_VIBRATION xInputVibration;
public: public:
int index; int index;
XInputDevice(int index, wchar_t *displayName) XInputDevice(int index, wchar_t* displayName)
: Device(XINPUT, OTHER, displayName) : Device(XINPUT, OTHER, displayName)
{ {
memset(ps2Vibration, 0, sizeof(ps2Vibration)); memset(ps2Vibration, 0, sizeof(ps2Vibration));
memset(&xInputVibration, 0, sizeof(xInputVibration)); memset(&xInputVibration, 0, sizeof(xInputVibration));
this->index = index; this->index = index;
int i; int i;
for (i = 0; i < 17; i++) { // Skip empty bit for (i = 0; i < 17; i++)
AddPhysicalControl(PRESSURE_BTN, i + (i > 10), 0); { // Skip empty bit
} AddPhysicalControl(PRESSURE_BTN, i + (i > 10), 0);
for (; i < 21; i++) { }
AddPhysicalControl(ABSAXIS, i + 2, 0); for (; i < 21; i++)
} {
AddFFAxis(L"Slow Motor", 0); AddPhysicalControl(ABSAXIS, i + 2, 0);
AddFFAxis(L"Fast Motor", 1); }
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT); AddFFAxis(L"Slow Motor", 0);
} AddFFAxis(L"Fast Motor", 1);
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT);
}
wchar_t *GetPhysicalControlName(PhysicalControl *c) wchar_t* GetPhysicalControlName(PhysicalControl* c)
{ {
const static wchar_t *names[] = { const static wchar_t* names[] = {
L"D-pad Up", L"D-pad Up",
L"D-pad Down", L"D-pad Down",
L"D-pad Left", L"D-pad Left",
L"D-pad Right", L"D-pad Right",
L"Start", L"Start",
L"Back", L"Back",
L"Left Thumb", L"Left Thumb",
L"Right Thumb", L"Right Thumb",
L"Left Shoulder", L"Left Shoulder",
L"Right Shoulder", L"Right Shoulder",
L"Guide", L"Guide",
L"A", L"A",
L"B", L"B",
L"X", L"X",
L"Y", L"Y",
L"Left Trigger", L"Left Trigger",
L"Right Trigger", L"Right Trigger",
L"Left Thumb X", L"Left Thumb X",
L"Left Thumb Y", L"Left Thumb Y",
L"Right Thumb X", L"Right Thumb X",
L"Right Thumb Y", L"Right Thumb Y",
}; };
unsigned int i = (unsigned int)(c - physicalControls); unsigned int i = (unsigned int)(c - physicalControls);
if (i < 21) { if (i < 21)
return (wchar_t *)names[i]; {
} return (wchar_t*)names[i];
return Device::GetPhysicalControlName(c); }
} return Device::GetPhysicalControlName(c);
}
int Activate(InitInfo *initInfo) int Activate(InitInfo* initInfo)
{ {
if (active) if (active)
Deactivate(); Deactivate();
if (!xInputActiveCount) { if (!xInputActiveCount)
pXInputEnable(1); {
} pXInputEnable(1);
xInputActiveCount++; }
active = 1; xInputActiveCount++;
AllocState(); active = 1;
return 1; AllocState();
} return 1;
}
int Update() int Update()
{ {
if (!active) if (!active)
return 0; return 0;
SCP_EXTN pressure; SCP_EXTN pressure;
if (!pXInputGetExtended || (ERROR_SUCCESS != pXInputGetExtended(index, &pressure))) { if (!pXInputGetExtended || (ERROR_SUCCESS != pXInputGetExtended(index, &pressure)))
XINPUT_STATE state; {
if (ERROR_SUCCESS != pXInputGetStateEx(index, &state)) { XINPUT_STATE state;
Deactivate(); if (ERROR_SUCCESS != pXInputGetStateEx(index, &state))
return 0; {
} Deactivate();
return 0;
}
int buttons = state.Gamepad.wButtons; int buttons = state.Gamepad.wButtons;
for (int i = 0; i < 15; i++) { for (int i = 0; i < 15; i++)
physicalControlState[i] = ((buttons >> physicalControls[i].id) & 1) << 16; {
} physicalControlState[i] = ((buttons >> physicalControls[i].id) & 1) << 16;
physicalControlState[15] = (int)(state.Gamepad.bLeftTrigger * 257.005); }
physicalControlState[16] = (int)(state.Gamepad.bRightTrigger * 257.005); physicalControlState[15] = (int)(state.Gamepad.bLeftTrigger * 257.005);
physicalControlState[17] = ShortToAxis(state.Gamepad.sThumbLX); physicalControlState[16] = (int)(state.Gamepad.bRightTrigger * 257.005);
physicalControlState[18] = ShortToAxis(state.Gamepad.sThumbLY); physicalControlState[17] = ShortToAxis(state.Gamepad.sThumbLX);
physicalControlState[19] = ShortToAxis(state.Gamepad.sThumbRX); physicalControlState[18] = ShortToAxis(state.Gamepad.sThumbLY);
physicalControlState[20] = ShortToAxis(state.Gamepad.sThumbRY); physicalControlState[19] = ShortToAxis(state.Gamepad.sThumbRX);
} else { physicalControlState[20] = ShortToAxis(state.Gamepad.sThumbRY);
physicalControlState[0] = (int)(pressure.SCP_UP * FULLY_DOWN); }
physicalControlState[1] = (int)(pressure.SCP_DOWN * FULLY_DOWN); else
physicalControlState[2] = (int)(pressure.SCP_LEFT * FULLY_DOWN); {
physicalControlState[3] = (int)(pressure.SCP_RIGHT * FULLY_DOWN); physicalControlState[0] = (int)(pressure.SCP_UP * FULLY_DOWN);
physicalControlState[4] = (int)(pressure.SCP_START * FULLY_DOWN); physicalControlState[1] = (int)(pressure.SCP_DOWN * FULLY_DOWN);
physicalControlState[5] = (int)(pressure.SCP_SELECT * FULLY_DOWN); physicalControlState[2] = (int)(pressure.SCP_LEFT * FULLY_DOWN);
physicalControlState[6] = (int)(pressure.SCP_L3 * FULLY_DOWN); physicalControlState[3] = (int)(pressure.SCP_RIGHT * FULLY_DOWN);
physicalControlState[7] = (int)(pressure.SCP_R3 * FULLY_DOWN); physicalControlState[4] = (int)(pressure.SCP_START * FULLY_DOWN);
physicalControlState[8] = (int)(pressure.SCP_L1 * FULLY_DOWN); physicalControlState[5] = (int)(pressure.SCP_SELECT * FULLY_DOWN);
physicalControlState[9] = (int)(pressure.SCP_R1 * FULLY_DOWN); physicalControlState[6] = (int)(pressure.SCP_L3 * FULLY_DOWN);
physicalControlState[10] = (int)(pressure.SCP_PS * FULLY_DOWN); physicalControlState[7] = (int)(pressure.SCP_R3 * FULLY_DOWN);
physicalControlState[11] = (int)(pressure.SCP_X * FULLY_DOWN); physicalControlState[8] = (int)(pressure.SCP_L1 * FULLY_DOWN);
physicalControlState[12] = (int)(pressure.SCP_C * FULLY_DOWN); physicalControlState[9] = (int)(pressure.SCP_R1 * FULLY_DOWN);
physicalControlState[13] = (int)(pressure.SCP_S * FULLY_DOWN); physicalControlState[10] = (int)(pressure.SCP_PS * FULLY_DOWN);
physicalControlState[14] = (int)(pressure.SCP_T * FULLY_DOWN); physicalControlState[11] = (int)(pressure.SCP_X * FULLY_DOWN);
physicalControlState[15] = (int)(pressure.SCP_L2 * FULLY_DOWN); physicalControlState[12] = (int)(pressure.SCP_C * FULLY_DOWN);
physicalControlState[16] = (int)(pressure.SCP_R2 * FULLY_DOWN); physicalControlState[13] = (int)(pressure.SCP_S * FULLY_DOWN);
physicalControlState[17] = (int)(pressure.SCP_LX * FULLY_DOWN); physicalControlState[14] = (int)(pressure.SCP_T * FULLY_DOWN);
physicalControlState[18] = (int)(pressure.SCP_LY * FULLY_DOWN); physicalControlState[15] = (int)(pressure.SCP_L2 * FULLY_DOWN);
physicalControlState[19] = (int)(pressure.SCP_RX * FULLY_DOWN); physicalControlState[16] = (int)(pressure.SCP_R2 * FULLY_DOWN);
physicalControlState[20] = (int)(pressure.SCP_RY * FULLY_DOWN); physicalControlState[17] = (int)(pressure.SCP_LX * FULLY_DOWN);
} physicalControlState[18] = (int)(pressure.SCP_LY * FULLY_DOWN);
return 1; physicalControlState[19] = (int)(pressure.SCP_RX * FULLY_DOWN);
} physicalControlState[20] = (int)(pressure.SCP_RY * FULLY_DOWN);
}
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; ps2Vibration[port][slot][motor] = force;
int newVibration[2] = {0, 0}; int newVibration[2] = {0, 0};
for (int p = 0; p < 2; p++) { for (int p = 0; p < 2; p++)
for (int s = 0; s < 4; s++) { {
int padtype = config.padConfigs[p][s].type; for (int s = 0; s < 4; s++)
for (int i = 0; i < pads[p][s][padtype].numFFBindings; i++) { {
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me. int padtype = config.padConfigs[p][s].type;
ForceFeedbackBinding *ffb = &pads[p][s][padtype].ffBindings[i]; for (int i = 0; i < pads[p][s][padtype].numFFBindings; i++)
newVibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); {
newVibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); // Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
} ForceFeedbackBinding* ffb = &pads[p][s][padtype].ffBindings[i];
} newVibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
} newVibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
newVibration[0] = abs(newVibration[0]); }
if (newVibration[0] > 65535) { }
newVibration[0] = 65535; }
} newVibration[0] = abs(newVibration[0]);
newVibration[1] = abs(newVibration[1]); if (newVibration[0] > 65535)
if (newVibration[1] > 65535) { {
newVibration[1] = 65535; newVibration[0] = 65535;
} }
if (newVibration[0] || newVibration[1] || newVibration[0] != xInputVibration.wLeftMotorSpeed || newVibration[1] != xInputVibration.wRightMotorSpeed) { newVibration[1] = abs(newVibration[1]);
XINPUT_VIBRATION newv = {(WORD)newVibration[0], (WORD)newVibration[1]}; if (newVibration[1] > 65535)
if (ERROR_SUCCESS == pXInputSetState(index, &newv)) { {
xInputVibration = newv; newVibration[1] = 65535;
} }
} if (newVibration[0] || newVibration[1] || newVibration[0] != xInputVibration.wLeftMotorSpeed || newVibration[1] != xInputVibration.wRightMotorSpeed)
} {
XINPUT_VIBRATION newv = {(WORD)newVibration[0], (WORD)newVibration[1]};
if (ERROR_SUCCESS == pXInputSetState(index, &newv))
{
xInputVibration = newv;
}
}
}
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) void SetEffect(ForceFeedbackBinding* binding, unsigned char force)
{ {
PadBindings pBackup = pads[0][0][0]; PadBindings pBackup = pads[0][0][0];
pads[0][0][0].ffBindings = binding; pads[0][0][0].ffBindings = binding;
pads[0][0][0].numFFBindings = 1; pads[0][0][0].numFFBindings = 1;
SetEffects(0, 0, binding->motor, 255); SetEffects(0, 0, binding->motor, 255);
pads[0][0][0] = pBackup; pads[0][0][0] = pBackup;
} }
void Deactivate() void Deactivate()
{ {
memset(&xInputVibration, 0, sizeof(xInputVibration)); memset(&xInputVibration, 0, sizeof(xInputVibration));
memset(ps2Vibration, 0, sizeof(ps2Vibration)); memset(ps2Vibration, 0, sizeof(ps2Vibration));
pXInputSetState(index, &xInputVibration); pXInputSetState(index, &xInputVibration);
FreeState(); FreeState();
if (active) { if (active)
if (!--xInputActiveCount) { {
pXInputEnable(0); if (!--xInputActiveCount)
} {
active = 0; pXInputEnable(0);
} }
} active = 0;
}
}
~XInputDevice() ~XInputDevice()
{ {
} }
}; };
void EnumXInputDevices() void EnumXInputDevices()
{ {
wchar_t temp[30]; wchar_t temp[30];
if (!pXInputSetState) { if (!pXInputSetState)
// XInput not installed, so don't repeatedly try to load it. {
if (xinputNotInstalled) // XInput not installed, so don't repeatedly try to load it.
return; if (xinputNotInstalled)
return;
// Prefer XInput 1.3 since SCP only has an XInput 1.3 wrapper right now. // 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 // Also use LoadLibrary and not LoadLibraryEx for XInput 1.3, since some
// Windows 7 systems have issues with it. // Windows 7 systems have issues with it.
// FIXME: Missing FreeLibrary call. // FIXME: Missing FreeLibrary call.
HMODULE hMod = LoadLibrary(L"xinput1_3.dll"); HMODULE hMod = LoadLibrary(L"xinput1_3.dll");
if (hMod == nullptr && IsWindows8OrGreater()) { if (hMod == nullptr && IsWindows8OrGreater())
hMod = LoadLibraryEx(L"XInput1_4.dll", nullptr, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); {
} hMod = LoadLibraryEx(L"XInput1_4.dll", nullptr, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
}
if (hMod) { if (hMod)
if ((pXInputEnable = (_XInputEnable)GetProcAddress(hMod, "XInputEnable")) && {
((pXInputGetStateEx = (_XInputGetStateEx)GetProcAddress(hMod, (LPCSTR)100)) || // Try Ex version first if ((pXInputEnable = (_XInputEnable)GetProcAddress(hMod, "XInputEnable")) &&
(pXInputGetStateEx = (_XInputGetStateEx)GetProcAddress(hMod, "XInputGetState")))) { ((pXInputGetStateEx = (_XInputGetStateEx)GetProcAddress(hMod, (LPCSTR)100)) || // Try Ex version first
pXInputGetExtended = (_XInputGetExtended)GetProcAddress(hMod, "XInputGetExtended"); (pXInputGetStateEx = (_XInputGetStateEx)GetProcAddress(hMod, "XInputGetState"))))
pXInputSetState = (_XInputSetState)GetProcAddress(hMod, "XInputSetState"); {
} pXInputGetExtended = (_XInputGetExtended)GetProcAddress(hMod, "XInputGetExtended");
} pXInputSetState = (_XInputSetState)GetProcAddress(hMod, "XInputSetState");
if (!pXInputSetState) { }
xinputNotInstalled = true; }
return; if (!pXInputSetState)
} {
} xinputNotInstalled = true;
pXInputEnable(1); return;
for (int i = 0; i < 4; i++) { }
wsprintfW(temp, L"XInput Pad %i", i); }
dm->AddDevice(new XInputDevice(i, temp)); pXInputEnable(1);
} for (int i = 0; i < 4; i++)
pXInputEnable(0); {
wsprintfW(temp, L"XInput Pad %i", i);
dm->AddDevice(new XInputDevice(i, temp));
}
pXInputEnable(0);
} }

View File

@ -2,155 +2,155 @@
// fichier Include Microsoft Visual C++. // fichier Include Microsoft Visual C++.
// Utilis<69> par PAD.rc // Utilis<69> par PAD.rc
// //
#define IDD_GENERAL 0x366 #define IDD_GENERAL 0x366
#define IDD_CONFIG 0x369 #define IDD_CONFIG 0x369
#define IDD_CONFIG_GUITAR 0x36A #define IDD_CONFIG_GUITAR 0x36A
#define IDD_PROPPAGE_LARGE 0x36B #define IDD_PROPPAGE_LARGE 0x36B
#define IDC_CURSOR1 0x36C #define IDC_CURSOR1 0x36C
#define IDD_DIAG 0x36D #define IDD_DIAG 0x36D
#define IDR_INI1 0x36E #define IDR_INI1 0x36E
#define IDD_CONFIG_POPN 0x36F #define IDD_CONFIG_POPN 0x36F
#define IDD_CONFIG_PS1_MOUSE 0x370 #define IDD_CONFIG_PS1_MOUSE 0x370
#define IDD_CONFIG_NEGCON 0x371 #define IDD_CONFIG_NEGCON 0x371
#define IDC_KB_DISABLE 0x344C #define IDC_KB_DISABLE 0x344C
#define IDC_KB_DI 0x344D #define IDC_KB_DI 0x344D
#define IDC_KB_WM 0x344E #define IDC_KB_WM 0x344E
#define IDC_KB_RAW 0x344F #define IDC_KB_RAW 0x344F
#define IDC_DISABLE_PAD1 0x3450 #define IDC_DISABLE_PAD1 0x3450
#define IDC_M_DISABLE 0x3451 #define IDC_M_DISABLE 0x3451
#define IDC_M_DI 0x3452 #define IDC_M_DI 0x3452
#define IDC_M_WM 0x3453 #define IDC_M_WM 0x3453
#define IDC_M_RAW 0x3454 #define IDC_M_RAW 0x3454
#define IDC_G_XI 0x3455 #define IDC_G_XI 0x3455
#define IDC_G_DI 0x3456 #define IDC_G_DI 0x3456
#define IDC_G_DS3 0x3457 #define IDC_G_DS3 0x3457
#define IDC_DEBUG_FILE 0x3458 #define IDC_DEBUG_FILE 0x3458
#define IDC_GUITAR1 0x3459 #define IDC_GUITAR1 0x3459
#define IDC_MULTITAP1 0x345A #define IDC_MULTITAP1 0x345A
#define IDC_MOUSE_UNFOCUS 0x345B #define IDC_MOUSE_UNFOCUS 0x345B
#define IDC_AXIS_BUTTONS 0x345C #define IDC_AXIS_BUTTONS 0x345C
#define IDC_MULTITAP2 0x345D #define IDC_MULTITAP2 0x345D
#define IDC_BACKGROUND 0x345E #define IDC_BACKGROUND 0x345E
#define IDC_MULTIPLE_BINDING 0x345F #define IDC_MULTIPLE_BINDING 0x345F
#define IDC_FORCE_HIDE 0x3460 #define IDC_FORCE_HIDE 0x3460
#define IDC_GH2_HACK 0x3461 #define IDC_GH2_HACK 0x3461
#define IDC_PAD_LIST 0x3462 #define IDC_PAD_LIST 0x3462
#define IDC_COMBO1 0x3463 #define IDC_COMBO1 0x3463
#define IDC_PAD_TYPE 0x3464 #define IDC_PAD_TYPE 0x3464
#define IDC_DIAG_LIST 0x3465 #define IDC_DIAG_LIST 0x3465
#define ID_SAVE 0x3466 #define ID_SAVE 0x3466
#define ID_LOAD 0x3467 #define ID_LOAD 0x3467
#define ID_RESTORE_DEFAULTS 0x3468 #define ID_RESTORE_DEFAULTS 0x3468
#define IDC_BINDINGS_LIST 0x3F00 #define IDC_BINDINGS_LIST 0x3F00
#define IDC_SLIDER_SENSITIVITY 0x4000 #define IDC_SLIDER_SENSITIVITY 0x4000
#define IDC_FLIP 0x4001 #define IDC_FLIP 0x4001
#define IDC_AXIS_DIRECTION 0x4002 #define IDC_AXIS_DIRECTION 0x4002
#define IDC_AXIS_CONTROL 0x4003 #define IDC_AXIS_CONTROL 0x4003
#define IDC_AXIS_SENSITIVITY 0x4004 #define IDC_AXIS_SENSITIVITY 0x4004
#define IDC_RAPID_FIRE 0x4005 #define IDC_RAPID_FIRE 0x4005
#define IDC_AXIS_DEVICE 0x4006 #define IDC_AXIS_DEVICE 0x4006
#define ID_SENSITIVITY 0x4007 #define ID_SENSITIVITY 0x4007
#define IDC_SLIDER_DEADZONE 0x4008 #define IDC_SLIDER_DEADZONE 0x4008
#define IDC_AXIS_DEADZONE 0x4009 #define IDC_AXIS_DEADZONE 0x4009
#define IDC_LABEL_SENSITIVITY 0x400A #define IDC_LABEL_SENSITIVITY 0x400A
#define IDC_LABEL_DEADZONE 0x400B #define IDC_LABEL_DEADZONE 0x400B
#define IDC_LABEL_SKIP_DEADZONE 0x400C #define IDC_LABEL_SKIP_DEADZONE 0x400C
#define IDC_SKIP_DEADZONE_OFF 0x400D #define IDC_SKIP_DEADZONE_OFF 0x400D
#define IDC_SLIDER_SKIP_DEADZONE 0x400E #define IDC_SLIDER_SKIP_DEADZONE 0x400E
#define IDC_AXIS_SKIP_DEADZONE 0x400F #define IDC_AXIS_SKIP_DEADZONE 0x400F
#define IDC_DPAD 0x40D0 #define IDC_DPAD 0x40D0
#define IDC_LSTICK 0x40D1 #define IDC_LSTICK 0x40D1
#define IDC_RSTICK 0x40D2 #define IDC_RSTICK 0x40D2
#define IDC_FACE 0x40D3 #define IDC_FACE 0x40D3
#define IDC_SHOULDER 0x40D4 #define IDC_SHOULDER 0x40D4
#define IDC_FACE_ANALOG 0x40D5 #define IDC_FACE_ANALOG 0x40D5
#define ID_MOUSE 0x40FF #define ID_MOUSE 0x40FF
#define ID_SELECT 0x4100 #define ID_SELECT 0x4100
#define ID_L3 0x4101 #define ID_L3 0x4101
#define ID_R3 0x4102 #define ID_R3 0x4102
#define ID_START 0x4103 #define ID_START 0x4103
#define ID_DPAD_UP 0x4104 #define ID_DPAD_UP 0x4104
#define ID_DPAD_RIGHT 0x4105 #define ID_DPAD_RIGHT 0x4105
#define ID_DPAD_DOWN 0x4106 #define ID_DPAD_DOWN 0x4106
#define ID_DPAD_LEFT 0x4107 #define ID_DPAD_LEFT 0x4107
#define ID_L2 0x4108 #define ID_L2 0x4108
#define ID_R2 0x4109 #define ID_R2 0x4109
#define ID_L1 0x410A #define ID_L1 0x410A
#define ID_R1 0x410B #define ID_R1 0x410B
#define ID_TRIANGLE 0x410C #define ID_TRIANGLE 0x410C
#define ID_CIRCLE 0x410D #define ID_CIRCLE 0x410D
#define ID_CROSS 0x410E #define ID_CROSS 0x410E
#define ID_SQUARE 0x410F #define ID_SQUARE 0x410F
#define ID_LSTICK_UP 0x4110 #define ID_LSTICK_UP 0x4110
#define ID_LSTICK_RIGHT 0x4111 #define ID_LSTICK_RIGHT 0x4111
#define ID_LSTICK_DOWN 0x4112 #define ID_LSTICK_DOWN 0x4112
#define ID_LSTICK_LEFT 0x4113 #define ID_LSTICK_LEFT 0x4113
#define ID_RSTICK_UP 0x4114 #define ID_RSTICK_UP 0x4114
#define ID_RSTICK_RIGHT 0x4115 #define ID_RSTICK_RIGHT 0x4115
#define ID_RSTICK_DOWN 0x4116 #define ID_RSTICK_DOWN 0x4116
#define ID_RSTICK_LEFT 0x4117 #define ID_RSTICK_LEFT 0x4117
#define ID_ANALOG 0x4118 #define ID_ANALOG 0x4118
#define ID_EXCLUDE 0x4119 #define ID_EXCLUDE 0x4119
#define ID_LOCK_BUTTONS 0x411A #define ID_LOCK_BUTTONS 0x411A
#define ID_LOCK_ALL_INPUT 0x411B #define ID_LOCK_ALL_INPUT 0x411B
#define ID_LOCK_DIRECTION 0x411C #define ID_LOCK_DIRECTION 0x411C
#define ID_TURBO_KEY 0x411D #define ID_TURBO_KEY 0x411D
#define ID_QUICK_SETUP 0x411E #define ID_QUICK_SETUP 0x411E
#define IDC_QUICK_SETUP_TEXT 0x411F #define IDC_QUICK_SETUP_TEXT 0x411F
#define IDC_FORCEFEEDBACK 0x4200 #define IDC_FORCEFEEDBACK 0x4200
#define IDC_FORCEFEEDBACK_FUNCTION 0x4201 #define IDC_FORCEFEEDBACK_FUNCTION 0x4201
#define ID_BIG_MOTOR 0x4202 #define ID_BIG_MOTOR 0x4202
#define ID_SMALL_MOTOR 0x4203 #define ID_SMALL_MOTOR 0x4203
#define ID_FORCEFEEDBACK_BOX 0x4204 #define ID_FORCEFEEDBACK_BOX 0x4204
#define IDC_CONFIGURE_ON_BIND 0x4230 #define IDC_CONFIGURE_ON_BIND 0x4230
#define IDC_DEVICE_SELECT 0x4231 #define IDC_DEVICE_SELECT 0x4231
#define ID_CLEAR 0x4232 #define ID_CLEAR 0x4232
#define ID_SPECIAL_INPUTS 0x4233 #define ID_SPECIAL_INPUTS 0x4233
#define ID_TEST 0x4300 #define ID_TEST 0x4300
#define ID_FF 0x4301 #define ID_FF 0x4301
#define IDC_FF_EFFECT 0x4302 #define IDC_FF_EFFECT 0x4302
#define IDC_FF_AXIS1_ENABLED 0x4310 #define IDC_FF_AXIS1_ENABLED 0x4310
#define IDC_FF_AXIS1 0x4311 #define IDC_FF_AXIS1 0x4311
#define IDC_FF_AXIS1_FLIP 0x4312 #define IDC_FF_AXIS1_FLIP 0x4312
#define IDC_FF_AXIS1_SCALE 0x4313 #define IDC_FF_AXIS1_SCALE 0x4313
#define IDC_FF_AXIS2_ENABLED 0x4320 #define IDC_FF_AXIS2_ENABLED 0x4320
#define IDC_FF_AXIS2 0x4321 #define IDC_FF_AXIS2 0x4321
#define IDC_FF_AXIS2_FLIP 0x4322 #define IDC_FF_AXIS2_FLIP 0x4322
#define IDC_FF_AXIS2_SCALE 0x4323 #define IDC_FF_AXIS2_SCALE 0x4323
#define IDC_FF_AXIS3_ENABLED 0x4330 #define IDC_FF_AXIS3_ENABLED 0x4330
#define IDC_FF_AXIS3 0x4331 #define IDC_FF_AXIS3 0x4331
#define IDC_FF_AXIS3_FLIP 0x4332 #define IDC_FF_AXIS3_FLIP 0x4332
#define IDC_FF_AXIS3_SCALE 0x4333 #define IDC_FF_AXIS3_SCALE 0x4333
#define IDC_FF_AXIS4_ENABLED 0x4340 #define IDC_FF_AXIS4_ENABLED 0x4340
#define IDC_FF_AXIS4 0x4341 #define IDC_FF_AXIS4 0x4341
#define IDC_FF_AXIS4_FLIP 0x4342 #define IDC_FF_AXIS4_FLIP 0x4342
#define IDC_FF_AXIS4_SCALE 0x4343 #define IDC_FF_AXIS4_SCALE 0x4343
#define IDC_FF_AXIS5_ENABLED 0x4350 #define IDC_FF_AXIS5_ENABLED 0x4350
#define IDC_FF_AXIS5 0x4351 #define IDC_FF_AXIS5 0x4351
#define IDC_FF_AXIS5_FLIP 0x4352 #define IDC_FF_AXIS5_FLIP 0x4352
#define IDC_FF_AXIS5_SCALE 0x4353 #define IDC_FF_AXIS5_SCALE 0x4353
#define IDC_FF_AXIS6_ENABLED 0x4360 #define IDC_FF_AXIS6_ENABLED 0x4360
#define IDC_FF_AXIS6 0x4361 #define IDC_FF_AXIS6 0x4361
#define IDC_FF_AXIS6_FLIP 0x4362 #define IDC_FF_AXIS6_FLIP 0x4362
#define IDC_FF_AXIS6_SCALE 0x4363 #define IDC_FF_AXIS6_SCALE 0x4363
#define IDC_FF_AXIS7_ENABLED 0x4370 #define IDC_FF_AXIS7_ENABLED 0x4370
#define IDC_FF_AXIS7 0x4371 #define IDC_FF_AXIS7 0x4371
#define IDC_FF_AXIS7_FLIP 0x4372 #define IDC_FF_AXIS7_FLIP 0x4372
#define IDC_FF_AXIS7_SCALE 0x4373 #define IDC_FF_AXIS7_SCALE 0x4373
#define IDC_FF_AXIS8_ENABLED 0x4380 #define IDC_FF_AXIS8_ENABLED 0x4380
#define IDC_FF_AXIS8 0x4381 #define IDC_FF_AXIS8 0x4381
#define IDC_FF_AXIS8_FLIP 0x4382 #define IDC_FF_AXIS8_FLIP 0x4382
#define IDC_FF_AXIS8_SCALE 0x4383 #define IDC_FF_AXIS8_SCALE 0x4383
#define ID_CONTROLS 0x4390 #define ID_CONTROLS 0x4390
#define ID_RESET_CONFIG 0x4391 #define ID_RESET_CONFIG 0x4391
// Next default values for new objects // Next default values for new objects
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 116 #define _APS_NEXT_RESOURCE_VALUE 116
#define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 5010 #define _APS_NEXT_CONTROL_VALUE 5010
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif
#endif #endif

View File

@ -85,43 +85,43 @@
/* All standard descriptors have these 2 fields in common */ /* All standard descriptors have these 2 fields in common */
struct usb_descriptor_header struct usb_descriptor_header
{ {
unsigned char bLength; unsigned char bLength;
unsigned char bDescriptorType; unsigned char bDescriptorType;
}; };
/* String descriptor */ /* String descriptor */
struct usb_string_descriptor struct usb_string_descriptor
{ {
unsigned char bLength; unsigned char bLength;
unsigned char bDescriptorType; unsigned char bDescriptorType;
unsigned short wData[1]; unsigned short wData[1];
}; };
/* HID descriptor */ /* HID descriptor */
struct usb_hid_descriptor struct usb_hid_descriptor
{ {
unsigned char bLength; unsigned char bLength;
unsigned char bDescriptorType; unsigned char bDescriptorType;
unsigned short bcdHID; unsigned short bcdHID;
unsigned char bCountryCode; unsigned char bCountryCode;
unsigned char bNumDescriptors; unsigned char bNumDescriptors;
}; };
/* Endpoint descriptor */ /* Endpoint descriptor */
#define USB_MAXENDPOINTS 32 #define USB_MAXENDPOINTS 32
struct usb_endpoint_descriptor struct usb_endpoint_descriptor
{ {
unsigned char bLength; unsigned char bLength;
unsigned char bDescriptorType; unsigned char bDescriptorType;
unsigned char bEndpointAddress; unsigned char bEndpointAddress;
unsigned char bmAttributes; unsigned char bmAttributes;
unsigned short wMaxPacketSize; unsigned short wMaxPacketSize;
unsigned char bInterval; unsigned char bInterval;
unsigned char bRefresh; unsigned char bRefresh;
unsigned char bSynchAddress; unsigned char bSynchAddress;
unsigned char *extra; /* Extra descriptors */ unsigned char* extra; /* Extra descriptors */
int extralen; int extralen;
}; };
#define USB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ #define USB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */
@ -137,76 +137,76 @@ struct usb_endpoint_descriptor
#define USB_MAXINTERFACES 32 #define USB_MAXINTERFACES 32
struct usb_interface_descriptor struct usb_interface_descriptor
{ {
unsigned char bLength; unsigned char bLength;
unsigned char bDescriptorType; unsigned char bDescriptorType;
unsigned char bInterfaceNumber; unsigned char bInterfaceNumber;
unsigned char bAlternateSetting; unsigned char bAlternateSetting;
unsigned char bNumEndpoints; unsigned char bNumEndpoints;
unsigned char bInterfaceClass; unsigned char bInterfaceClass;
unsigned char bInterfaceSubClass; unsigned char bInterfaceSubClass;
unsigned char bInterfaceProtocol; unsigned char bInterfaceProtocol;
unsigned char iInterface; unsigned char iInterface;
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor* endpoint;
unsigned char *extra; /* Extra descriptors */ unsigned char* extra; /* Extra descriptors */
int extralen; int extralen;
}; };
#define USB_MAXALTSETTING 128 /* Hard limit */ #define USB_MAXALTSETTING 128 /* Hard limit */
struct usb_interface struct usb_interface
{ {
struct usb_interface_descriptor *altsetting; struct usb_interface_descriptor* altsetting;
int num_altsetting; int num_altsetting;
}; };
/* Configuration descriptor information.. */ /* Configuration descriptor information.. */
#define USB_MAXCONFIG 8 #define USB_MAXCONFIG 8
struct usb_config_descriptor struct usb_config_descriptor
{ {
unsigned char bLength; unsigned char bLength;
unsigned char bDescriptorType; unsigned char bDescriptorType;
unsigned short wTotalLength; unsigned short wTotalLength;
unsigned char bNumInterfaces; unsigned char bNumInterfaces;
unsigned char bConfigurationValue; unsigned char bConfigurationValue;
unsigned char iConfiguration; unsigned char iConfiguration;
unsigned char bmAttributes; unsigned char bmAttributes;
unsigned char MaxPower; unsigned char MaxPower;
struct usb_interface *interface; struct usb_interface* interface;
unsigned char *extra; /* Extra descriptors */ unsigned char* extra; /* Extra descriptors */
int extralen; int extralen;
}; };
/* Device descriptor */ /* Device descriptor */
struct usb_device_descriptor struct usb_device_descriptor
{ {
unsigned char bLength; unsigned char bLength;
unsigned char bDescriptorType; unsigned char bDescriptorType;
unsigned short bcdUSB; unsigned short bcdUSB;
unsigned char bDeviceClass; unsigned char bDeviceClass;
unsigned char bDeviceSubClass; unsigned char bDeviceSubClass;
unsigned char bDeviceProtocol; unsigned char bDeviceProtocol;
unsigned char bMaxPacketSize0; unsigned char bMaxPacketSize0;
unsigned short idVendor; unsigned short idVendor;
unsigned short idProduct; unsigned short idProduct;
unsigned short bcdDevice; unsigned short bcdDevice;
unsigned char iManufacturer; unsigned char iManufacturer;
unsigned char iProduct; unsigned char iProduct;
unsigned char iSerialNumber; unsigned char iSerialNumber;
unsigned char bNumConfigurations; unsigned char bNumConfigurations;
}; };
struct usb_ctrl_setup struct usb_ctrl_setup
{ {
unsigned char bRequestType; unsigned char bRequestType;
unsigned char bRequest; unsigned char bRequest;
unsigned short wValue; unsigned short wValue;
unsigned short wIndex; unsigned short wIndex;
unsigned short wLength; unsigned short wLength;
}; };
/* /*
@ -258,52 +258,52 @@ struct usb_ctrl_setup
struct usb_device struct usb_device
{ {
struct usb_device *next, *prev; struct usb_device *next, *prev;
char filename[LIBUSB_PATH_MAX]; char filename[LIBUSB_PATH_MAX];
struct usb_bus *bus; struct usb_bus* bus;
struct usb_device_descriptor descriptor; struct usb_device_descriptor descriptor;
struct usb_config_descriptor *config; struct usb_config_descriptor* config;
void *dev; /* Darwin support */ void* dev; /* Darwin support */
unsigned char devnum; unsigned char devnum;
unsigned char num_children; unsigned char num_children;
struct usb_device **children; struct usb_device** children;
}; };
struct usb_bus struct usb_bus
{ {
struct usb_bus *next, *prev; struct usb_bus *next, *prev;
char dirname[LIBUSB_PATH_MAX]; char dirname[LIBUSB_PATH_MAX];
struct usb_device *devices; struct usb_device* devices;
unsigned long location; unsigned long location;
struct usb_device *root_dev; struct usb_device* root_dev;
}; };
/* Version information, Windows specific */ /* Version information, Windows specific */
struct usb_version struct usb_version
{ {
struct struct
{ {
int major; int major;
int minor; int minor;
int micro; int micro;
int nano; int nano;
} dll; } dll;
struct struct
{ {
int major; int major;
int minor; int minor;
int micro; int micro;
int nano; int nano;
} driver; } driver;
}; };
@ -327,48 +327,48 @@ extern "C" {
/* Function prototypes */ /* Function prototypes */
/* usb.c */ /* usb.c */
usb_dev_handle *usb_open(struct usb_device *dev); usb_dev_handle* usb_open(struct usb_device* dev);
int usb_close(usb_dev_handle *dev); int usb_close(usb_dev_handle* dev);
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, int usb_get_string(usb_dev_handle* dev, int index, int langid, char* buf,
size_t buflen); 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); size_t buflen);
/* descriptors.c */ /* descriptors.c */
int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep, int usb_get_descriptor_by_endpoint(usb_dev_handle* udev, int ep,
unsigned char type, unsigned char index, unsigned char type, unsigned char index,
void *buf, int size); 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); unsigned char index, void* buf, int size);
/* <arch>.c */ /* <arch>.c */
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int usb_bulk_write(usb_dev_handle* dev, int ep, char* bytes, int size,
int timeout); 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 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 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 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 value, int index, char* bytes, int size,
int timeout); int timeout);
int usb_set_configuration(usb_dev_handle *dev, int configuration); int usb_set_configuration(usb_dev_handle* dev, int configuration);
int usb_claim_interface(usb_dev_handle *dev, int interface); int usb_claim_interface(usb_dev_handle* dev, int interface);
int usb_release_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_set_altinterface(usb_dev_handle* dev, int alternate);
int usb_resetep(usb_dev_handle *dev, unsigned int ep); int usb_resetep(usb_dev_handle* dev, unsigned int ep);
int usb_clear_halt(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_reset(usb_dev_handle* dev);
char *usb_strerror(void); char* usb_strerror(void);
void usb_init(void); void usb_init(void);
void usb_set_debug(int level); void usb_set_debug(int level);
int usb_find_busses(void); int usb_find_busses(void);
int usb_find_devices(void); int usb_find_devices(void);
struct usb_device *usb_device(usb_dev_handle *dev); struct usb_device* usb_device(usb_dev_handle* dev);
struct usb_bus *usb_get_busses(void); struct usb_bus* usb_get_busses(void);
/* Windows specific functions */ /* Windows specific functions */
@ -376,40 +376,40 @@ struct usb_bus *usb_get_busses(void);
#define LIBUSB_HAS_INSTALL_SERVICE_NP 1 #define LIBUSB_HAS_INSTALL_SERVICE_NP 1
int usb_install_service_np(void); int usb_install_service_np(void);
void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance, void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show); LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1 #define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1
int usb_uninstall_service_np(void); int usb_uninstall_service_np(void);
void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance, void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show); LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_INSTALL_DRIVER_NP 1 #define LIBUSB_HAS_INSTALL_DRIVER_NP 1
int usb_install_driver_np(const char *inf_file); int usb_install_driver_np(const char* inf_file);
void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance, void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show); LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_TOUCH_INF_FILE_NP 1 #define LIBUSB_HAS_TOUCH_INF_FILE_NP 1
int usb_touch_inf_file_np(const char *inf_file); int usb_touch_inf_file_np(const char* inf_file);
void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance, void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show); LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1 #define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1
int usb_install_needs_restart_np(void); 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); 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); 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); unsigned char ep);
int usb_submit_async(void *context, char *bytes, int size); int usb_submit_async(void* context, char* bytes, int size);
int usb_reap_async(void *context, int timeout); int usb_reap_async(void* context, int timeout);
int usb_reap_async_nocancel(void *context, int timeout); int usb_reap_async_nocancel(void* context, int timeout);
int usb_cancel_async(void *context); int usb_cancel_async(void* context);
int usb_free_async(void **context); int usb_free_async(void** context);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -950,9 +950,6 @@
<ItemGroup> <ItemGroup>
<Manifest Include="..\PCSX2.manifest" /> <Manifest Include="..\PCSX2.manifest" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Image Include="..\..\PAD\Windows\frog.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" /> <ImportGroup Label="ExtensionTargets" />
</Project> </Project>

View File

@ -2185,9 +2185,4 @@
<Filter>AppHost\Resources</Filter> <Filter>AppHost\Resources</Filter>
</Manifest> </Manifest>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Image Include="..\..\PAD\Windows\frog.ico">
<Filter>System\Ps2\PAD</Filter>
</Image>
</ItemGroup>
</Project> </Project>