LilyPad: Add separate bindings for each pad type (#1609)

Adds separate bindings for each of the pad types (DualShock2,
Guitar,Pop'n Music). This allows the user to change the button
configuration to better suit the Guitar and Pop'n Music pads without
messing up the bindings already setup for the DS2.

Close #1576.
This commit is contained in:
FlatOutPS2 2016-11-06 22:59:19 +01:00 committed by Jonathan Li
parent 5ff9e94a2e
commit 5d90afe648
10 changed files with 569 additions and 315 deletions

View File

@ -77,7 +77,7 @@ int selected = 0;
// we shouldn't make our own.
bool createIniDir = true;
HWND hWnds[2][4];
HWND hWnds[2][4][numPadTypes];
HWND hWndGeneral = 0;
struct GeneralSettingsBool
@ -111,7 +111,7 @@ const GeneralSettingsBool BoolOptionsInfo[] = {
{L"Turbo Key Hack", IDC_TURBO_KEY_HACK, 0},
};
void Populate(int port, int slot);
void Populate(int port, int slot, int padtype);
void SetupLogSlider(HWND hWndSlider)
{
@ -256,18 +256,21 @@ void RefreshEnabledDevicesAndDisplay(int updateDeviceList = 0, HWND hWnd = 0, in
}
}
if (populate) {
for (int i = 0; i < 8; i++) {
Populate(i & 1, i >> 1);
for (int j = 0; j < numPadTypes; j++) {
for (int i = 0; i < 8; i++) {
Populate(i & 1, i >> 1, j);
}
}
}
}
wchar_t *GetCommandStringW(u8 command, int port, int slot)
{
int padtype = config.padConfigs[port][slot].type;
static wchar_t temp[34];
if (command >= 0x20 && command <= 0x27) {
if (config.padConfigs[port][slot].type == GuitarPad && (command == 0x20 || command == 0x22)) {
HWND hWnd = GetDlgItem(hWnds[port][slot], 0x10F0 + command);
if (padtype == GuitarPad && (command == 0x20 || command == 0x22)) {
HWND hWnd = GetDlgItem(hWnds[port][slot][padtype], 0x10F0 + command);
int res = GetWindowTextW(hWnd, temp, 20);
if ((unsigned int)res - 1 <= 18)
return temp;
@ -281,7 +284,7 @@ wchar_t *GetCommandStringW(u8 command, int port, int slot)
}
/* Get text from the buttons. */
if (command >= 0x0C && command <= 0x28) {
HWND hWnd = GetDlgItem(hWnds[port][slot], 0x10F0 + command);
HWND hWnd = GetDlgItem(hWnds[port][slot][padtype], 0x10F0 + command);
if (!hWnd) {
wchar_t *strings[] = {
L"Lock Buttons",
@ -359,13 +362,14 @@ void CALLBACK PADsetSettingsDir(const char *dir)
}
int GetBinding(int port, int slot, int index, Device *&dev, Binding *&b, ForceFeedbackBinding *&ffb);
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo, int deadZone);
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, unsigned int padtype, int command, int sensitivity, int turbo, int deadZone);
int CreateEffectBinding(Device *dev, wchar_t *effectName, unsigned int port, unsigned int slot, unsigned int motor, ForceFeedbackBinding **binding);
int CreateEffectBinding(Device *dev, wchar_t *effectName, unsigned int port, unsigned int slot, unsigned int padtype, unsigned int motor, ForceFeedbackBinding **binding);
void SelChanged(int port, int slot)
{
HWND hWnd = hWnds[port][slot];
int padtype = config.padConfigs[port][slot].type;
HWND hWnd = hWnds[port][slot][padtype];
if (!hWnd)
return;
HWND hWndTemp, hWndList = GetDlgItem(hWnd, IDC_LIST);
@ -598,30 +602,32 @@ void UnselectAll(HWND hWnd)
int GetItemIndex(int port, int slot, Device *dev, ForceFeedbackBinding *binding)
{
int count = 0;
int padtype = config.padConfigs[port][slot].type;
for (int i = 0; i < dm->numDevices; i++) {
Device *dev2 = dm->devices[i];
if (!dev2->enabled)
continue;
if (dev2 != dev) {
count += dev2->pads[port][slot].numBindings + dev2->pads[port][slot].numFFBindings;
count += dev2->pads[port][slot][padtype].numBindings + dev2->pads[port][slot][padtype].numFFBindings;
continue;
}
return count += dev2->pads[port][slot].numBindings + (binding - dev2->pads[port][slot].ffBindings);
return count += dev2->pads[port][slot][padtype].numBindings + (binding - dev2->pads[port][slot][padtype].ffBindings);
}
return -1;
}
int GetItemIndex(int port, int slot, Device *dev, Binding *binding)
{
int count = 0;
int padtype = config.padConfigs[port][slot].type;
for (int i = 0; i < dm->numDevices; i++) {
Device *dev2 = dm->devices[i];
if (!dev2->enabled)
continue;
if (dev2 != dev) {
count += dev2->pads[port][slot].numBindings + dev2->pads[port][slot].numFFBindings;
count += dev2->pads[port][slot][padtype].numBindings + dev2->pads[port][slot][padtype].numFFBindings;
continue;
}
return count += binding - dev->pads[port][slot].bindings;
return count += binding - dev->pads[port][slot][padtype].bindings;
}
return -1;
}
@ -629,9 +635,10 @@ int GetItemIndex(int port, int slot, Device *dev, Binding *binding)
// Doesn't check if already displayed.
int ListBoundCommand(int port, int slot, Device *dev, Binding *b)
{
if (!hWnds[port][slot])
int padtype = config.padConfigs[port][slot].type;
if (!hWnds[port][slot][padtype])
return -1;
HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST);
HWND hWndList = GetDlgItem(hWnds[port][slot][padtype], IDC_LIST);
int index = -1;
if (hWndList) {
index = GetItemIndex(port, slot, dev, b);
@ -656,9 +663,10 @@ int ListBoundCommand(int port, int slot, Device *dev, Binding *b)
int ListBoundEffect(int port, int slot, Device *dev, ForceFeedbackBinding *b)
{
if (!hWnds[port][slot])
int padtype = config.padConfigs[port][slot].type;
if (!hWnds[port][slot][padtype])
return -1;
HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST);
HWND hWndList = GetDlgItem(hWnds[port][slot][padtype], IDC_LIST);
int index = -1;
if (hWndList) {
index = GetItemIndex(port, slot, dev, b);
@ -685,9 +693,10 @@ int ListBoundEffect(int port, int slot, Device *dev, ForceFeedbackBinding *b)
// Only for use with control bindings. Affects all highlighted bindings.
void ChangeValue(int port, int slot, int *newSensitivity, int *newTurbo, int *newDeadZone)
{
if (!hWnds[port][slot])
int padtype = config.padConfigs[port][slot].type;
if (!hWnds[port][slot][padtype])
return;
HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST);
HWND hWndList = GetDlgItem(hWnds[port][slot][padtype], IDC_LIST);
int count = ListView_GetSelectedCount(hWndList);
if (count < 1)
return;
@ -717,16 +726,17 @@ void ChangeValue(int port, int slot, int *newSensitivity, int *newTurbo, int *ne
b->turbo = *newTurbo;
}
}
PropSheet_Changed(hWndProp, hWnds[port][slot]);
PropSheet_Changed(hWndProp, hWnds[port][slot][padtype]);
SelChanged(port, slot);
}
// Only for use with effect bindings.
void ChangeEffect(int port, int slot, int id, int *newForce, unsigned int *newEffectType)
{
if (!hWnds[port][slot])
int padtype = config.padConfigs[port][slot].type;
if (!hWnds[port][slot][padtype])
return;
HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST);
HWND hWndList = GetDlgItem(hWnds[port][slot][padtype], IDC_LIST);
int i = ListView_GetSelectedCount(hWndList);
if (i != 1)
return;
@ -748,17 +758,17 @@ void ChangeEffect(int port, int slot, int id, int *newForce, unsigned int *newEf
index = ListBoundEffect(port, slot, dev, ffb);
ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED);
}
PropSheet_Changed(hWndProp, hWnds[port][slot]);
PropSheet_Changed(hWndProp, hWnds[port][slot][padtype]);
SelChanged(port, slot);
}
void Populate(int port, int slot)
void Populate(int port, int slot, int padtype)
{
if (!hWnds[port][slot])
if (!hWnds[port][slot][padtype])
return;
HWND hWnd = GetDlgItem(hWnds[port][slot], IDC_LIST);
HWND hWnd = GetDlgItem(hWnds[port][slot][padtype], IDC_LIST);
ListView_DeleteAllItems(hWnd);
int i, j;
@ -768,16 +778,16 @@ void Populate(int port, int slot)
Device *dev = dm->devices[j];
if (!dev->enabled)
continue;
for (i = 0; i < dev->pads[port][slot].numBindings; i++) {
ListBoundCommand(port, slot, dev, dev->pads[port][slot].bindings + i);
for (i = 0; i < dev->pads[port][slot][padtype].numBindings; i++) {
ListBoundCommand(port, slot, dev, dev->pads[port][slot][padtype].bindings + i);
}
for (i = 0; i < dev->pads[port][slot].numFFBindings; i++) {
ListBoundEffect(port, slot, dev, dev->pads[port][slot].ffBindings + i);
for (i = 0; i < dev->pads[port][slot][padtype].numFFBindings; i++) {
ListBoundEffect(port, slot, dev, dev->pads[port][slot][padtype].ffBindings + i);
}
}
config.multipleBinding = multipleBinding;
hWnd = GetDlgItem(hWnds[port][slot], IDC_FORCEFEEDBACK);
hWnd = GetDlgItem(hWnds[port][slot][padtype], IDC_FORCEFEEDBACK);
SendMessage(hWnd, CB_RESETCONTENT, 0, 0);
int added = 0;
for (i = 0; i < dm->numDevices; i++) {
@ -790,8 +800,8 @@ void Populate(int port, int slot)
}
SendMessage(hWnd, CB_SETCURSEL, 0, 0);
EnableWindow(hWnd, added != 0);
EnableWindow(GetDlgItem(hWnds[port][slot], ID_BIG_MOTOR), added != 0);
EnableWindow(GetDlgItem(hWnds[port][slot], ID_SMALL_MOTOR), added != 0);
EnableWindow(GetDlgItem(hWnds[port][slot][padtype], ID_BIG_MOTOR), added != 0);
EnableWindow(GetDlgItem(hWnds[port][slot][padtype], ID_SMALL_MOTOR), added != 0);
SelChanged(port, slot);
}
@ -869,24 +879,26 @@ int SaveSettings(wchar_t *file = 0)
int bindingCount = 0;
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
for (int j = 0; j < dev->pads[port][slot].numBindings; j++) {
Binding *b = dev->pads[port][slot].bindings + j;
VirtualControl *c = &dev->virtualControls[b->controlIndex];
wsprintfW(temp, L"Binding %i", bindingCount++);
wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i, %i, %i", c->uid, port, b->command, b->sensitivity, b->turbo, slot, b->deadZone);
noError &= WritePrivateProfileStringW(id, temp, temp2, file);
}
for (int j = 0; j < dev->pads[port][slot].numFFBindings; j++) {
ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings + j;
ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex];
wsprintfW(temp, L"FF Binding %i", ffBindingCount++);
wsprintfW(temp2, L"%s %i, %i, %i", eff->effectID, port, b->motor, slot);
for (int k = 0; k < dev->numFFAxes; k++) {
ForceFeedbackAxis *axis = dev->ffAxes + k;
AxisEffectInfo *info = b->axes + k;
wsprintfW(wcschr(temp2, 0), L", %i, %i", axis->id, info->force);
for (int padtype = 0; padtype < numPadTypes; padtype++) {
for (int j = 0; j < dev->pads[port][slot][padtype].numBindings; j++) {
Binding *b = dev->pads[port][slot][padtype].bindings + j;
VirtualControl *c = &dev->virtualControls[b->controlIndex];
wsprintfW(temp, L"Binding %i", bindingCount++);
wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i, %i, %i, %i", c->uid, port, b->command, b->sensitivity, b->turbo, slot, b->deadZone, padtype);
noError &= WritePrivateProfileStringW(id, temp, temp2, file);
}
for (int j = 0; j < dev->pads[port][slot][padtype].numFFBindings; j++) {
ForceFeedbackBinding *b = dev->pads[port][slot][padtype].ffBindings + j;
ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex];
wsprintfW(temp, L"FF Binding %i", ffBindingCount++);
wsprintfW(temp2, L"%s %i, %i, %i, %i", eff->effectID, port, b->motor, slot, padtype);
for (int k = 0; k < dev->numFFAxes; k++) {
ForceFeedbackAxis *axis = dev->ffAxes + k;
AxisEffectInfo *info = b->axes + k;
wsprintfW(wcschr(temp2, 0), L", %i, %i", axis->id, info->force);
}
noError &= WritePrivateProfileStringW(id, temp, temp2, file);
}
noError &= WritePrivateProfileStringW(id, temp, temp2, file);
}
}
}
@ -936,7 +948,6 @@ int LoadSettings(int force, wchar_t *file)
for (int i = 0; i < sizeof(BoolOptionsInfo) / sizeof(BoolOptionsInfo[0]); i++) {
config.bools[i] = GetPrivateProfileBool(L"General Settings", BoolOptionsInfo[i].name, BoolOptionsInfo[i].defaultValue, file);
}
config.closeHacks = (u8)GetPrivateProfileIntW(L"General Settings", L"Close Hacks", 0, file);
if (config.closeHacks & 1)
config.closeHacks &= ~2;
@ -959,6 +970,7 @@ int LoadSettings(int force, wchar_t *file)
}
}
bool oldIni = false;
int i = 0;
int multipleBinding = config.multipleBinding;
// Disabling multiple binding only prevents new multiple bindings.
@ -999,7 +1011,7 @@ int LoadSettings(int force, wchar_t *file)
}
last = 1;
unsigned int uid;
int port, command, sensitivity, turbo, slot = 0, deadZone = 0;
int port, command, sensitivity, turbo, slot = 0, deadZone = 0, padtype = 0;
int w = 0;
char string[1000];
while (temp2[w]) {
@ -1007,13 +1019,21 @@ int LoadSettings(int force, wchar_t *file)
w++;
}
string[w] = 0;
int len = sscanf(string, " %i , %i , %i , %i , %i , %i , %i", &uid, &port, &command, &sensitivity, &turbo, &slot, &deadZone);
int len = sscanf(string, " %i , %i , %i , %i , %i , %i , %i , %i", &uid, &port, &command, &sensitivity, &turbo, &slot, &deadZone, &padtype);
if (len >= 5 && type) {
VirtualControl *c = dev->GetVirtualControl(uid);
if (!c)
c = dev->AddVirtualControl(uid, -1);
if (c) {
BindCommand(dev, uid, port, slot, command, sensitivity, turbo, deadZone);
if (len < 8) { // If ini file is imported from older version, make sure bindings aren't applied to "Unplugged" padtype.
oldIni = true;
if (config.padConfigs[port][slot].type != 0) {
padtype = config.padConfigs[port][slot].type;
} else {
padtype = 1;
}
}
BindCommand(dev, uid, port, slot, padtype, command, sensitivity, turbo, deadZone);
}
}
}
@ -1029,7 +1049,7 @@ int LoadSettings(int force, wchar_t *file)
continue;
}
last = 1;
int port, slot, motor;
int port, slot, motor, padtype;
int w = 0;
char string[1000];
char effect[1000];
@ -1040,8 +1060,18 @@ int LoadSettings(int force, wchar_t *file)
string[w] = 0;
// wcstok not in ntdll. More effore than its worth to shave off
// whitespace without it.
if (sscanf(string, " %s %i , %i , %i", effect, &port, &motor, &slot) == 4) {
char *s = strchr(strchr(strchr(string, ',') + 1, ',') + 1, ',');
if (sscanf(string, " %20s %i , %i , %i , %i", effect, &port, &motor, &slot, &padtype) == 5) {
char *s;
if (oldIni) { // Make sure bindings aren't applied to "Unplugged" padtype and FF settings are read from old location.
if (config.padConfigs[port][slot].type != 0) {
padtype = config.padConfigs[port][slot].type;
} else {
padtype = 1;
}
s = strchr(strchr(strchr(string, ',') + 1, ',') + 1, ',');
} else {
s = strchr(strchr(strchr(strchr(string, ',') + 1, ',') + 1, ',') + 1, ',');
}
if (!s)
continue;
s++;
@ -1059,7 +1089,7 @@ int LoadSettings(int force, wchar_t *file)
// eff = &dev->ffEffectTypes[dev->numFFEffectTypes-1];
}
ForceFeedbackBinding *b;
CreateEffectBinding(dev, temp2, port, slot, motor, &b);
CreateEffectBinding(dev, temp2, port, slot, padtype, motor, &b);
if (b) {
while (1) {
int axisID = atoi(s);
@ -1096,10 +1126,14 @@ int LoadSettings(int force, wchar_t *file)
inline int GetPort(HWND hWnd, int *slot)
{
for (int i = 0; i < sizeof(hWnds) / sizeof(hWnds[0][0]); i++) {
if (hWnds[i & 1][i >> 1] == hWnd) {
*slot = i >> 1;
return i & 1;
if (sizeof(hWnds) / sizeof(hWnds[0][0][0]) != (2 * 4 * numPadTypes))
MessageBoxA(hWndProp, "The number of detected configurations does not equal the expected number of configurations.", "Pad configurations error", MB_OK | MB_ICONERROR);
for (int j = 0; j < numPadTypes; j++) {
for (int i = 0; i < 8; i++) {
if (hWnds[i & 1][i >> 1][j] == hWnd) {
*slot = i >> 1;
return i & 1;
}
}
}
*slot = 0;
@ -1129,68 +1163,71 @@ int GetBinding(int port, int slot, int index, Device *&dev, Binding *&b, ForceFe
{
ffb = 0;
b = 0;
int padtype = config.padConfigs[port][slot].type;
for (int i = 0; i < dm->numDevices; i++) {
dev = dm->devices[i];
if (!dev->enabled)
continue;
if (index < dev->pads[port][slot].numBindings) {
b = dev->pads[port][slot].bindings + index;
if (index < dev->pads[port][slot][padtype].numBindings) {
b = dev->pads[port][slot][padtype].bindings + index;
return 1;
}
index -= dev->pads[port][slot].numBindings;
index -= dev->pads[port][slot][padtype].numBindings;
if (index < dev->pads[port][slot].numFFBindings) {
ffb = dev->pads[port][slot].ffBindings + index;
if (index < dev->pads[port][slot][padtype].numFFBindings) {
ffb = dev->pads[port][slot][padtype].ffBindings + index;
return 1;
}
index -= dev->pads[port][slot].numFFBindings;
index -= dev->pads[port][slot][padtype].numFFBindings;
}
return 0;
}
// Only used when deleting things from ListView. Will remove from listview if needed.
void DeleteBinding(int port, int slot, Device *dev, Binding *b)
void DeleteBinding(int port, int slot, int padtype, Device *dev, Binding *b)
{
if (dev->enabled && hWnds[port][slot]) {
if (dev->enabled && hWnds[port][slot][padtype]) {
int count = GetItemIndex(port, slot, dev, b);
if (count >= 0) {
HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST);
HWND hWndList = GetDlgItem(hWnds[port][slot][padtype], IDC_LIST);
if (hWndList) {
ListView_DeleteItem(hWndList, count);
}
}
}
Binding *bindings = dev->pads[port][slot].bindings;
Binding *bindings = dev->pads[port][slot][padtype].bindings;
int i = b - bindings;
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot].numBindings - i - 1));
dev->pads[port][slot].numBindings--;
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot][padtype].numBindings - i - 1));
dev->pads[port][slot][padtype].numBindings--;
}
void DeleteBinding(int port, int slot, Device *dev, ForceFeedbackBinding *b)
{
if (dev->enabled && hWnds[port][slot]) {
int padtype = config.padConfigs[port][slot].type;
if (dev->enabled && hWnds[port][slot][padtype]) {
int count = GetItemIndex(port, slot, dev, b);
if (count >= 0) {
HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST);
HWND hWndList = GetDlgItem(hWnds[port][slot][padtype], IDC_LIST);
if (hWndList) {
ListView_DeleteItem(hWndList, count);
}
}
}
ForceFeedbackBinding *bindings = dev->pads[port][slot].ffBindings;
ForceFeedbackBinding *bindings = dev->pads[port][slot][padtype].ffBindings;
int i = b - bindings;
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot].numFFBindings - i - 1));
dev->pads[port][slot].numFFBindings--;
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot][padtype].numFFBindings - i - 1));
dev->pads[port][slot][padtype].numFFBindings--;
}
int DeleteByIndex(int port, int slot, int index)
{
int padtype = config.padConfigs[port][slot].type;
ForceFeedbackBinding *ffb;
Binding *b;
Device *dev;
if (GetBinding(port, slot, index, dev, b, ffb)) {
if (b) {
DeleteBinding(port, slot, dev, b);
DeleteBinding(port, slot, padtype, dev, b);
} else {
DeleteBinding(port, slot, dev, ffb);
}
@ -1201,9 +1238,10 @@ int DeleteByIndex(int port, int slot, int index)
int DeleteSelected(int port, int slot)
{
if (!hWnds[port][slot])
int padtype = config.padConfigs[port][slot].type;
if (!hWnds[port][slot][padtype])
return 0;
HWND hWnd = GetDlgItem(hWnds[port][slot], IDC_LIST);
HWND hWnd = GetDlgItem(hWnds[port][slot][padtype], IDC_LIST);
int changes = 0;
while (1) {
int index = ListView_GetNextItem(hWnd, -1, LVNI_SELECTED);
@ -1215,7 +1253,7 @@ int DeleteSelected(int port, int slot)
return changes;
}
int CreateEffectBinding(Device *dev, wchar_t *effectID, unsigned int port, unsigned int slot, unsigned int motor, ForceFeedbackBinding **binding)
int CreateEffectBinding(Device *dev, wchar_t *effectID, unsigned int port, unsigned int slot, unsigned int padtype, unsigned int motor, ForceFeedbackBinding **binding)
{
// Checks needed because I use this directly when loading bindings.
// Note: dev->numFFAxes *can* be 0, for loading from file.
@ -1234,28 +1272,28 @@ int CreateEffectBinding(Device *dev, wchar_t *effectID, unsigned int port, unsig
return -1;
}
int effectIndex = eff - dev->ffEffectTypes;
dev->pads[port][slot].ffBindings = (ForceFeedbackBinding *)realloc(dev->pads[port][slot].ffBindings, (dev->pads[port][slot].numFFBindings + 1) * sizeof(ForceFeedbackBinding));
int newIndex = dev->pads[port][slot].numFFBindings;
while (newIndex && dev->pads[port][slot].ffBindings[newIndex - 1].motor >= motor) {
dev->pads[port][slot].ffBindings[newIndex] = dev->pads[port][slot].ffBindings[newIndex - 1];
dev->pads[port][slot][padtype].ffBindings = (ForceFeedbackBinding *)realloc(dev->pads[port][slot][padtype].ffBindings, (dev->pads[port][slot][padtype].numFFBindings + 1) * sizeof(ForceFeedbackBinding));
int newIndex = dev->pads[port][slot][padtype].numFFBindings;
while (newIndex && dev->pads[port][slot][padtype].ffBindings[newIndex - 1].motor >= motor) {
dev->pads[port][slot][padtype].ffBindings[newIndex] = dev->pads[port][slot][padtype].ffBindings[newIndex - 1];
newIndex--;
}
ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings + newIndex;
ForceFeedbackBinding *b = dev->pads[port][slot][padtype].ffBindings + newIndex;
b->axes = (AxisEffectInfo *)calloc(dev->numFFAxes, sizeof(AxisEffectInfo));
b->motor = motor;
b->effectIndex = effectIndex;
dev->pads[port][slot].numFFBindings++;
dev->pads[port][slot][padtype].numFFBindings++;
if (binding)
*binding = b;
return ListBoundEffect(port, slot, dev, b);
}
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo, int deadZone)
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, unsigned int padtype, int command, int sensitivity, int turbo, int deadZone)
{
// Checks needed because I use this directly when loading bindings.
if (port > 1 || slot > 3) {
if (port > 1 || slot > 3 || padtype >= numPadTypes)
return -1;
}
if (!sensitivity)
sensitivity = BASE_SENSITIVITY;
if ((uid >> 16) & (PSHBTN | TGLBTN)) {
@ -1277,7 +1315,7 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int s
// Add before deleting. Means I won't scroll up one line when scrolled down to bottom.
int controlIndex = c - dev->virtualControls;
int index = 0;
PadBindings *p = dev->pads[port] + slot;
PadBindings *p = dev->pads[port][slot] + padtype;
p->bindings = (Binding *)realloc(p->bindings, (p->numBindings + 1) * sizeof(Binding));
for (index = p->numBindings; index > 0; index--) {
if (p->bindings[index - 1].controlIndex < controlIndex)
@ -1319,19 +1357,20 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int s
newBindingIndex--;
count--;
}
DeleteBinding(port, slot, dev, b);
DeleteBinding(port, slot, padtype, dev, b);
}
if (!config.multipleBinding) {
for (int port2 = 0; port2 < 2; port2++) {
for (int slot2 = 0; slot2 < 4; slot2++) {
if (port2 == port && slot2 == slot)
continue;
PadBindings *p = dev->pads[port2] + slot2;
int padtype2 = config.padConfigs[port2][slot2].type;
PadBindings *p = dev->pads[port2][slot2] + padtype2;
for (int i = 0; i < p->numBindings; i++) {
Binding *b = p->bindings + i;
int uid2 = dev->virtualControls[b->controlIndex].uid;
if (b->controlIndex == controlIndex || (!((uid2 ^ uid) & 0xFFFFFF) && ((uid | uid2) & (UID_POV | UID_AXIS)))) {
DeleteBinding(port2, slot2, dev, b);
DeleteBinding(port2, slot2, padtype2, dev, b);
i--;
}
}
@ -1380,6 +1419,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
int index = (hWnd == PropSheet_IndexToHwnd(hWndProp, 1));
int slot;
int port = GetPort(hWnd, &slot);
int padtype = config.padConfigs[port][slot].type;
HWND hWndList = GetDlgItem(hWnd, IDC_LIST);
switch (msg) {
case WM_INITDIALOG: {
@ -1398,14 +1438,15 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
selected = 0;
port = (int)((PROPSHEETPAGE *)lParam)->lParam & 1;
slot = (int)((PROPSHEETPAGE *)lParam)->lParam >> 1;
hWnds[port][slot] = hWnd;
padtype = config.padConfigs[port][slot].type;
hWnds[port][slot][padtype] = hWnd;
SendMessage(hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
SetupLogSlider(GetDlgItem(hWnd, IDC_SLIDER1));
SetupLogSlider(GetDlgItem(hWnd, IDC_SLIDER_DEADZONE));
if (port || slot)
EnableWindow(GetDlgItem(hWnd, ID_IGNORE), 0);
Populate(port, slot);
Populate(port, slot, padtype);
} break;
case WM_DEVICECHANGE:
if (wParam == DBT_DEVNODES_CHANGED) {
@ -1443,12 +1484,12 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
UnselectAll(hWndList);
int index = -1;
if (command == 0x7F && dev->api == IGNORE_KEYBOARD) {
index = BindCommand(dev, uid, 0, 0, command, BASE_SENSITIVITY, 0, 0);
index = BindCommand(dev, uid, 0, 0, 0, command, BASE_SENSITIVITY, 0, 0);
} else if (command < 0x30) {
index = BindCommand(dev, uid, port, slot, command, BASE_SENSITIVITY, 0, 0);
index = BindCommand(dev, uid, port, slot, padtype, command, BASE_SENSITIVITY, 0, 0);
}
if (index >= 0) {
PropSheet_Changed(hWndProp, hWnds[port][slot]);
PropSheet_Changed(hWndProp, hWnds[port][slot][padtype]);
ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED);
ListView_EnsureVisible(hWndList, index, 0);
}
@ -1529,7 +1570,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
uid = (uid & 0x00FFFFFF) | axisUIDs[cbsel];
Binding backup = *b;
DeleteSelected(port, slot);
int index = BindCommand(dev, uid, port, slot, backup.command, backup.sensitivity, backup.turbo, backup.deadZone);
int index = BindCommand(dev, uid, port, slot, padtype, backup.command, backup.sensitivity, backup.turbo, backup.deadZone);
ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED);
PropSheet_Changed(hWndProp, hWnd);
}
@ -1564,7 +1605,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
else
effectID = L"13541C22-8E33-11D0-9AD0-00A0C9A06E35";
}
int count = CreateEffectBinding(dev, effectID, port, slot, cmd - ID_BIG_MOTOR, &b);
int count = CreateEffectBinding(dev, effectID, port, slot, padtype, cmd - ID_BIG_MOTOR, &b);
if (b) {
int needSet = 1;
if (dev->api == XINPUT && dev->numFFAxes == 2) {
@ -1710,6 +1751,75 @@ int GetPadString(wchar_t *string, unsigned int port, unsigned int slot)
return 1;
}
// Returns 0 if pad doesn't exist due to mtap settings, as a convenience.
int GetPadTypeString(wchar_t *string, unsigned int port, unsigned int slot, unsigned int padtype)
{
if (!slot && !config.multitap[port]) {
wsprintfW(string, L"Pad %i, %s", port + 1, padTypes[padtype]);
} else {
wsprintfW(string, L"Pad %i%c, %s", port + 1, 'A' + slot, padTypes[padtype]);
if (!config.multitap[port])
return 0;
}
return 1;
}
bool ProfilesBindingCheck(unsigned int port, unsigned int slot, unsigned int padtype)
{
bool showWarning = true;
int count = 0;
for (int i = 0; i < dm->numDevices; i++) {
for (int portCheck = 0; portCheck < 2; portCheck++) {
int maxslot = 1;
if (config.multitap[portCheck])
maxslot = 4;
if (portCheck == port && !config.multitap[portCheck])
continue;
for (int slotCheck = 0; slotCheck < maxslot; slotCheck++) {
if (portCheck == port && slotCheck == slot)
continue;
int padtypeCheck = config.padConfigs[portCheck][slotCheck].type;
PadBindings *pCheck = dm->devices[i]->pads[portCheck][slotCheck] + padtypeCheck;
PadBindings *pActive = dm->devices[i]->pads[port][slot] + padtype;
for (int j = 0; j < pCheck->numBindings; j++) {
for (int k = 0; k < pActive->numBindings; k++) {
Binding *bCheck = pCheck->bindings + j;
Binding *bActive = pActive->bindings + k;
int uidCheck = dm->devices[i]->virtualControls[bCheck->controlIndex].uid;
int uidActive = dm->devices[i]->virtualControls[bActive->controlIndex].uid;
if (bCheck->controlIndex == bActive->controlIndex || (!((uidActive ^ uidCheck) & 0xFFFFFF) && ((uidCheck | uidActive) & (UID_POV | UID_AXIS)))) {
if (showWarning) {
int msgboxID = MessageBoxA(hWndProp, "Warning! You have selected a pad type that has one or several bindings that conflict with the active pad type of the opposing port or slot(s).\n\n"
"Do you want to keep the bindings of the pad type you are switching to?\n"
"Click ''Yes'' to continue without deleting any binding.\n"
"Click ''No'' to continue and delete any conflicting bindings from the selected pad type.\n"
"Click ''Cancel'' to revert to the previously selected pad type and avoid any further action.\n\n"
"Note: Enable the 'Allow binding multiple PS2 controls to one PC control' option to allow conflicting bindings between opposing ports and slots, and avoid this warning and the possibility of bindings getting deleted.",
"Duplicate Binding Warning", MB_YESNOCANCEL | MB_DEFBUTTON3 | MB_ICONWARNING);
switch (msgboxID) {
case IDCANCEL:
return false;
break;
case IDYES:
return true;
break;
case IDNO:
showWarning = false;
break;
}
}
DeleteBinding(port, slot, padtype, dm->devices[i], bActive);
k--;
count++;
}
}
}
}
}
}
return true;
}
void UpdatePadPages()
{
HPROPSHEETPAGE pages[10];
@ -1784,6 +1894,7 @@ void UpdatePadList(HWND hWnd)
for (port = 0; port < 2; port++) {
for (slot = 0; slot < 4; slot++) {
int padtype = config.padConfigs[port][slot].type;
wchar_t text[25];
if (!GetPadString(text, port, slot))
continue;
@ -1799,9 +1910,9 @@ void UpdatePadList(HWND hWnd)
}
item.iSubItem = 1;
if (numPadTypes - 1 < (unsigned int)config.padConfigs[port][slot].type)
config.padConfigs[port][slot].type = Dualshock2Pad;
wcsncpy(item.pszText, padTypes[config.padConfigs[port][slot].type], 25);
if (numPadTypes - 1 < (unsigned int)padtype)
padtype = Dualshock2Pad;
wcsncpy(item.pszText, padTypes[padtype], 25);
//if (!slot && !config.padConfigs[port][slot].type)
// item.pszText = L"Unplugged (Kinda)";
@ -1813,7 +1924,7 @@ void UpdatePadList(HWND hWnd)
Device *dev = dm->devices[i];
if (!dev->enabled)
continue;
count += dev->pads[port][slot].numBindings + dev->pads[port][slot].numFFBindings;
count += dev->pads[port][slot][padtype].numBindings + dev->pads[port][slot][padtype].numFFBindings;
}
wsprintf(text, L"%i", count);
item.pszText = text;
@ -1891,7 +2002,6 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L
for (int j = 0; j < sizeof(BoolOptionsInfo) / sizeof(BoolOptionsInfo[0]); j++) {
CheckDlgButton(hWnd, BoolOptionsInfo[j].ControlId, BST_CHECKED * config.bools[j]);
}
CheckDlgButton(hWnd, IDC_CLOSE_HACK1, BST_CHECKED * (config.closeHacks & 1));
CheckDlgButton(hWnd, IDC_CLOSE_HACK2, BST_CHECKED * ((config.closeHacks & 2) >> 1));
@ -1919,6 +2029,8 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L
if (sel < 0 || !ListIndexToPortAndSlot(index, &port, &slot))
break;
if (sel != config.padConfigs[port][slot].type) {
if (!config.multipleBinding && !ProfilesBindingCheck(port, slot, sel))
break;
config.padConfigs[port][slot].type = (PadType)sel;
UpdatePadList(hWnd);
UpdatePadPages();
@ -1986,7 +2098,6 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L
for (int j = 0; j < sizeof(BoolOptionsInfo) / sizeof(BoolOptionsInfo[0]); j++) {
config.bools[j] = (IsDlgButtonChecked(hWnd, BoolOptionsInfo[j].ControlId) == BST_CHECKED);
}
config.closeHacks = (IsDlgButtonChecked(hWnd, IDC_CLOSE_HACK1) == BST_CHECKED) |
((IsDlgButtonChecked(hWnd, IDC_CLOSE_HACK2) == BST_CHECKED) << 1);
@ -2038,34 +2149,59 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L
if (n->hdr.code == NM_RCLICK) {
UpdatePadList(hWnd);
int index = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED);
int port1, slot1, port2, slot2;
int port1, slot1, port2, slot2, padtype1, padtype2;
if (!ListIndexToPortAndSlot(index, &port1, &slot1))
break;
padtype1 = config.padConfigs[port1][slot1].type;
HMENU hMenu = CreatePopupMenu();
if (!hMenu)
break;
MENUITEMINFOW info;
for (port2 = 1; port2 >= 0; port2--) {
for (slot2 = 3; slot2 >= 0; slot2--) {
wchar_t text[40];
wchar_t pad[20];
if (!GetPadString(pad, port2, slot2))
continue;
info.cbSize = sizeof(info);
info.fMask = MIIM_STRING | MIIM_ID;
info.dwTypeData = text;
if (port2 == port1 && slot2 == slot1) {
int index = GetMenuItemCount(hMenu);
wsprintfW(text, L"Clear %s Bindings", pad);
info.wID = -1;
InsertMenuItemW(hMenu, index, 1, &info);
info.fMask = MIIM_TYPE;
info.fType = MFT_SEPARATOR;
InsertMenuItemW(hMenu, index, 1, &info);
} else {
info.wID = port2 + 2 * slot2 + 1;
wsprintfW(text, L"Swap with %s", pad);
InsertMenuItemW(hMenu, 0, 1, &info);
for (int IndividualPadtypes = 1; IndividualPadtypes >= 0; IndividualPadtypes--) {
info.fMask = MIIM_TYPE;
info.fType = MFT_SEPARATOR;
InsertMenuItemW(hMenu, 0, 1, &info);
for (port2 = 1; port2 >= 0; port2--) {
for (slot2 = 3; slot2 >= 0; slot2--) {
padtype2 = config.padConfigs[port2][slot2].type;
wchar_t text[40];
wchar_t pad[40];
if (IndividualPadtypes == 0) {
if (!GetPadString(pad, port2, slot2))
continue;
} else {
if (!GetPadTypeString(pad, port2, slot2, padtype2))
continue;
}
info.cbSize = sizeof(info);
info.fMask = MIIM_STRING | MIIM_ID;
info.dwTypeData = text;
if (port2 == port1 && slot2 == slot1 && padtype2 == padtype1) {
int index = GetMenuItemCount(hMenu);
wsprintfW(text, L"Clear %s Bindings", pad);
if (IndividualPadtypes == 0) {
info.wID = -1;
wsprintfW(text, L"Clear all %s Bindings", pad);
} else {
info.wID = -2;
wsprintfW(text, L"Clear %s Bindings only", pad);
}
InsertMenuItemW(hMenu, index, 1, &info);
info.fMask = MIIM_TYPE;
info.fType = MFT_SEPARATOR;
InsertMenuItemW(hMenu, index, 1, &info);
} else if (!(port2 == port1 && slot2 == slot1)) {
info.wID = port2 + 2 * slot2 + 1;
if (IndividualPadtypes == 1) {
if (!config.multipleBinding && padtype2 != padtype1)
continue;
info.wID += 8;
wsprintfW(text, L"Swap with %s bindings only", pad);
} else {
wsprintfW(text, L"Swap all bindings with %s", pad);
}
InsertMenuItemW(hMenu, 0, 1, &info);
}
}
}
}
@ -2075,30 +2211,62 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L
DestroyMenu(hMenu);
if (!res)
break;
bool swapIndividualPadtypes = false;
if (res > 0) {
if (res > 8) {
res -= 8;
swapIndividualPadtypes = true;
}
res--;
slot2 = res / 2;
port2 = res & 1;
padtype2 = config.padConfigs[port2][slot2].type;
PadConfig padCfgTemp = config.padConfigs[port1][slot1];
config.padConfigs[port1][slot1] = config.padConfigs[port2][slot2];
config.padConfigs[port2][slot2] = padCfgTemp;
if (swapIndividualPadtypes) {
config.padConfigs[port2][slot2].type = config.padConfigs[port1][slot1].type;
config.padConfigs[port1][slot1].type = padCfgTemp.type;
}
for (int i = 0; i < dm->numDevices; i++) {
if (dm->devices[i]->type == IGNORE)
continue;
PadBindings bindings = dm->devices[i]->pads[port1][slot1];
dm->devices[i]->pads[port1][slot1] = dm->devices[i]->pads[port2][slot2];
dm->devices[i]->pads[port2][slot2] = bindings;
if (swapIndividualPadtypes) {
PadBindings bindings = dm->devices[i]->pads[port1][slot1][padtype1];
dm->devices[i]->pads[port1][slot1][padtype1] = dm->devices[i]->pads[port2][slot2][padtype2];
dm->devices[i]->pads[port2][slot2][padtype2] = bindings;
} else {
for (int padtype = 0; padtype < numPadTypes; padtype++) {
PadBindings bindings = dm->devices[i]->pads[port1][slot1][padtype];
dm->devices[i]->pads[port1][slot1][padtype] = dm->devices[i]->pads[port2][slot2][padtype];
dm->devices[i]->pads[port2][slot2][padtype] = bindings;
}
}
}
} else {
if (res == -2) {
swapIndividualPadtypes = true;
}
for (int i = 0; i < dm->numDevices; i++) {
if (dm->devices[i]->type == IGNORE)
continue;
free(dm->devices[i]->pads[port1][slot1].bindings);
for (int j = 0; j < dm->devices[i]->pads[port1][slot1].numFFBindings; j++) {
free(dm->devices[i]->pads[port1][slot1].ffBindings[j].axes);
if (swapIndividualPadtypes) {
free(dm->devices[i]->pads[port1][slot1][padtype1].bindings);
for (int j = 0; j < dm->devices[i]->pads[port1][slot1][padtype1].numFFBindings; j++) {
free(dm->devices[i]->pads[port1][slot1][padtype1].ffBindings[j].axes);
}
free(dm->devices[i]->pads[port1][slot1][padtype1].ffBindings);
memset(&dm->devices[i]->pads[port1][slot1][padtype1], 0, sizeof(dm->devices[i]->pads[port1][slot1][padtype1]));
} else {
for (int padtype = 0; padtype < numPadTypes; padtype++) {
free(dm->devices[i]->pads[port1][slot1][padtype].bindings);
for (int j = 0; j < dm->devices[i]->pads[port1][slot1][padtype].numFFBindings; j++) {
free(dm->devices[i]->pads[port1][slot1][padtype].ffBindings[j].axes);
}
free(dm->devices[i]->pads[port1][slot1][padtype].ffBindings);
memset(&dm->devices[i]->pads[port1][slot1][padtype], 0, sizeof(dm->devices[i]->pads[port1][slot1][padtype]));
}
}
free(dm->devices[i]->pads[port1][slot1].ffBindings);
memset(&dm->devices[i]->pads[port1][slot1], 0, sizeof(dm->devices[i]->pads[port1][slot1]));
}
}
UpdatePadPages();

View File

@ -20,14 +20,6 @@
extern u8 ps2e;
enum PadType {
DisabledPad,
Dualshock2Pad,
GuitarPad,
PopnPad
};
const int numPadTypes = 4;
extern const wchar_t *padTypes[numPadTypes];
struct PadConfig

View File

@ -48,65 +48,109 @@ Display Name=XInput Pad 0
Instance ID=XInput Pad 0
API=4
Type=3
Binding 0=0x00200000, 0, 20, 65536, 0, 0, 1
Binding 1=0x00200001, 0, 22, 65536, 0, 0, 1
Binding 2=0x00200002, 0, 23, 65536, 0, 0, 1
Binding 3=0x00200003, 0, 21, 65536, 0, 0, 1
Binding 4=0x00200004, 0, 19, 65536, 0, 0, 1
Binding 5=0x00200005, 0, 16, 65536, 0, 0, 1
Binding 6=0x00200006, 0, 17, 65536, 0, 0, 1
Binding 7=0x00200007, 0, 18, 65536, 0, 0, 1
Binding 8=0x00200008, 0, 26, 65536, 0, 0, 1
Binding 9=0x00200009, 0, 27, 65536, 0, 0, 1
Binding 10=0x0020000A, 0, 40, 65536, 0, 0, 1
Binding 11=0x0020000C, 0, 30, 65536, 0, 0, 1
Binding 12=0x0020000D, 0, 29, 65536, 0, 0, 1
Binding 13=0x0020000E, 0, 31, 65536, 0, 0, 1
Binding 14=0x0020000F, 0, 28, 65536, 0, 0, 1
Binding 15=0x00200010, 0, 24, 65536, 0, 0, 1
Binding 16=0x00200011, 0, 25, 65536, 0, 0, 1
Binding 17=0x01020013, 0, 33, 87183, 0, 0, 13172
Binding 18=0x02020013, 0, 35, 87183, 0, 0, 13172
Binding 19=0x01020014, 0, 32, 87183, 0, 0, 13172
Binding 20=0x02020014, 0, 34, 87183, 0, 0, 13172
Binding 21=0x01020015, 0, 37, 87183, 0, 0, 13172
Binding 22=0x02020015, 0, 39, 87183, 0, 0, 13172
Binding 23=0x01020016, 0, 36, 87183, 0, 0, 13172
Binding 24=0x02020016, 0, 38, 87183, 0, 0, 13172
FF Binding 0=Constant 0, 0, 0, 0, 65536, 1, 0
FF Binding 1=Constant 0, 1, 0, 0, 0, 1, 65536
Binding 0=0x00200000, 0, 20, 65536, 0, 0, 1, 1
Binding 1=0x00200001, 0, 22, 65536, 0, 0, 1, 1
Binding 2=0x00200002, 0, 23, 65536, 0, 0, 1, 1
Binding 3=0x00200003, 0, 21, 65536, 0, 0, 1, 1
Binding 4=0x00200004, 0, 19, 65536, 0, 0, 1, 1
Binding 5=0x00200005, 0, 16, 65536, 0, 0, 1, 1
Binding 6=0x00200006, 0, 17, 65536, 0, 0, 1, 1
Binding 7=0x00200007, 0, 18, 65536, 0, 0, 1, 1
Binding 8=0x00200008, 0, 26, 65536, 0, 0, 1, 1
Binding 9=0x00200009, 0, 27, 65536, 0, 0, 1, 1
Binding 10=0x0020000A, 0, 40, 65536, 0, 0, 1, 1
Binding 11=0x0020000C, 0, 30, 65536, 0, 0, 1, 1
Binding 12=0x0020000D, 0, 29, 65536, 0, 0, 1, 1
Binding 13=0x0020000E, 0, 31, 65536, 0, 0, 1, 1
Binding 14=0x0020000F, 0, 28, 65536, 0, 0, 1, 1
Binding 15=0x00200010, 0, 24, 65536, 0, 0, 1, 1
Binding 16=0x00200011, 0, 25, 65536, 0, 0, 1, 1
Binding 17=0x01020013, 0, 33, 87183, 0, 0, 13172, 1
Binding 18=0x02020013, 0, 35, 87183, 0, 0, 13172, 1
Binding 19=0x01020014, 0, 32, 87183, 0, 0, 13172, 1
Binding 20=0x02020014, 0, 34, 87183, 0, 0, 13172, 1
Binding 21=0x01020015, 0, 37, 87183, 0, 0, 13172, 1
Binding 22=0x02020015, 0, 39, 87183, 0, 0, 13172, 1
Binding 23=0x01020016, 0, 36, 87183, 0, 0, 13172, 1
Binding 24=0x02020016, 0, 38, 87183, 0, 0, 13172, 1
Binding 25=0x00200000, 0, 20, 65536, 0, 0, 1, 2
Binding 26=0x00200001, 0, 22, 65536, 0, 0, 1, 2
Binding 27=0x00200004, 0, 19, 65536, 0, 0, 1, 2
Binding 28=0x00200005, 0, 16, 65536, 0, 0, 1, 2
Binding 29=0x00200008, 0, 25, 65536, 0, 0, 1, 2
Binding 30=0x00200009, 0, 28, 65536, 0, 0, 1, 2
Binding 31=0x0020000F, 0, 31, 65536, 0, 0, 1, 2
Binding 32=0x00200010, 0, 29, 65536, 0, 0, 1, 2
Binding 33=0x00200011, 0, 31, 65536, 0, 0, 1, 2
Binding 34=0x01020014, 0, 32, 65536, 0, 0, 13172, 2
Binding 35=0x02020014, 0, 34, 65536, 0, 0, 13172, 2
Binding 36=0x00200002, 0, 28, 65536, 0, 0, 1, 3
Binding 37=0x00200003, 0, 27, 65536, 0, 0, 1, 3
Binding 38=0x00200004, 0, 19, 65536, 0, 0, 1, 3
Binding 39=0x00200005, 0, 16, 65536, 0, 0, 1, 3
Binding 40=0x00200008, 0, 30, 65536, 0, 0, 1, 3
Binding 41=0x00200009, 0, 31, 65536, 0, 0, 1, 3
Binding 42=0x0020000C, 0, 25, 65536, 0, 0, 1, 3
Binding 43=0x0020000D, 0, 24, 65536, 0, 0, 1, 3
Binding 44=0x0020000E, 0, 26, 65536, 0, 0, 1, 3
Binding 45=0x00200010, 0, 29, 65536, 0, 0, 1, 3
Binding 46=0x00200011, 0, 20, 65536, 0, 0, 1, 3
FF Binding 0=Constant 0, 0, 0, 1, 0, 65536, 1, 0
FF Binding 1=Constant 0, 1, 0, 1, 0, 0, 1, 65536
[Device 1]
Display Name=XInput Pad 1
Instance ID=XInput Pad 1
API=4
Type=3
Binding 0=0x00200000, 1, 20, 65536, 0, 0, 1
Binding 1=0x00200001, 1, 22, 65536, 0, 0, 1
Binding 2=0x00200002, 1, 23, 65536, 0, 0, 1
Binding 3=0x00200003, 1, 21, 65536, 0, 0, 1
Binding 4=0x00200004, 1, 19, 65536, 0, 0, 1
Binding 5=0x00200005, 1, 16, 65536, 0, 0, 1
Binding 6=0x00200006, 1, 17, 65536, 0, 0, 1
Binding 7=0x00200007, 1, 18, 65536, 0, 0, 1
Binding 8=0x00200008, 1, 26, 65536, 0, 0, 1
Binding 9=0x00200009, 1, 27, 65536, 0, 0, 1
Binding 10=0x0020000A, 1, 40, 65536, 0, 0, 1
Binding 11=0x0020000C, 1, 30, 65536, 0, 0, 1
Binding 12=0x0020000D, 1, 29, 65536, 0, 0, 1
Binding 13=0x0020000E, 1, 31, 65536, 0, 0, 1
Binding 14=0x0020000F, 1, 28, 65536, 0, 0, 1
Binding 15=0x00200010, 1, 24, 65536, 0, 0, 1
Binding 16=0x00200011, 1, 25, 65536, 0, 0, 1
Binding 17=0x01020013, 1, 33, 87183, 0, 0, 13172
Binding 18=0x02020013, 1, 35, 87183, 0, 0, 13172
Binding 19=0x01020014, 1, 32, 87183, 0, 0, 13172
Binding 20=0x02020014, 1, 34, 87183, 0, 0, 13172
Binding 21=0x01020015, 1, 37, 87183, 0, 0, 13172
Binding 22=0x02020015, 1, 39, 87183, 0, 0, 13172
Binding 23=0x01020016, 1, 36, 87183, 0, 0, 13172
Binding 24=0x02020016, 1, 38, 87183, 0, 0, 13172
FF Binding 0=Constant 1, 0, 0, 0, 65536, 1, 0
FF Binding 1=Constant 1, 1, 0, 0, 0, 1, 65536
Binding 0=0x00200000, 1, 20, 65536, 0, 0, 1, 1
Binding 1=0x00200001, 1, 22, 65536, 0, 0, 1, 1
Binding 2=0x00200002, 1, 23, 65536, 0, 0, 1, 1
Binding 3=0x00200003, 1, 21, 65536, 0, 0, 1, 1
Binding 4=0x00200004, 1, 19, 65536, 0, 0, 1, 1
Binding 5=0x00200005, 1, 16, 65536, 0, 0, 1, 1
Binding 6=0x00200006, 1, 17, 65536, 0, 0, 1, 1
Binding 7=0x00200007, 1, 18, 65536, 0, 0, 1, 1
Binding 8=0x00200008, 1, 26, 65536, 0, 0, 1, 1
Binding 9=0x00200009, 1, 27, 65536, 0, 0, 1, 1
Binding 10=0x0020000A, 1, 40, 65536, 0, 0, 1, 1
Binding 11=0x0020000C, 1, 30, 65536, 0, 0, 1, 1
Binding 12=0x0020000D, 1, 29, 65536, 0, 0, 1, 1
Binding 13=0x0020000E, 1, 31, 65536, 0, 0, 1, 1
Binding 14=0x0020000F, 1, 28, 65536, 0, 0, 1, 1
Binding 15=0x00200010, 1, 24, 65536, 0, 0, 1, 1
Binding 16=0x00200011, 1, 25, 65536, 0, 0, 1, 1
Binding 17=0x01020013, 1, 33, 87183, 0, 0, 13172, 1
Binding 18=0x02020013, 1, 35, 87183, 0, 0, 13172, 1
Binding 19=0x01020014, 1, 32, 87183, 0, 0, 13172, 1
Binding 20=0x02020014, 1, 34, 87183, 0, 0, 13172, 1
Binding 21=0x01020015, 1, 37, 87183, 0, 0, 13172, 1
Binding 22=0x02020015, 1, 39, 87183, 0, 0, 13172, 1
Binding 23=0x01020016, 1, 36, 87183, 0, 0, 13172, 1
Binding 24=0x02020016, 1, 38, 87183, 0, 0, 13172, 1
Binding 25=0x00200000, 1, 20, 65536, 0, 0, 1, 2
Binding 26=0x00200001, 1, 22, 65536, 0, 0, 1, 2
Binding 27=0x00200004, 1, 19, 65536, 0, 0, 1, 2
Binding 28=0x00200005, 1, 16, 65536, 0, 0, 1, 2
Binding 29=0x00200008, 1, 25, 65536, 0, 0, 1, 2
Binding 30=0x00200009, 1, 28, 65536, 0, 0, 1, 2
Binding 31=0x0020000F, 1, 31, 65536, 0, 0, 1, 2
Binding 32=0x00200010, 1, 29, 65536, 0, 0, 1, 2
Binding 33=0x00200011, 1, 31, 65536, 0, 0, 1, 2
Binding 34=0x01020014, 1, 32, 65536, 0, 0, 13172, 2
Binding 35=0x02020014, 1, 34, 65536, 0, 0, 13172, 2
Binding 36=0x00200002, 1, 28, 65536, 0, 0, 1, 3
Binding 37=0x00200003, 1, 27, 65536, 0, 0, 1, 3
Binding 38=0x00200004, 1, 19, 65536, 0, 0, 1, 3
Binding 39=0x00200005, 1, 16, 65536, 0, 0, 1, 3
Binding 40=0x00200008, 1, 30, 65536, 0, 0, 1, 3
Binding 41=0x00200009, 1, 31, 65536, 0, 0, 1, 3
Binding 42=0x0020000C, 1, 25, 65536, 0, 0, 1, 3
Binding 43=0x0020000D, 1, 24, 65536, 0, 0, 1, 3
Binding 44=0x0020000E, 1, 26, 65536, 0, 0, 1, 3
Binding 45=0x00200010, 1, 29, 65536, 0, 0, 1, 3
Binding 46=0x00200011, 1, 20, 65536, 0, 0, 1, 3
FF Binding 0=Constant 1, 0, 0, 1, 0, 65536, 1, 0
FF Binding 1=Constant 1, 1, 0, 1, 0, 0, 1, 65536
[Device 12]
Display Name=XInput Pad 2
Instance ID=XInput Pad 2

View File

@ -19,6 +19,7 @@
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include "InputManager.h"
#include "Config.h"
#include "VKey.h"
#include "DirectInput.h"
@ -149,13 +150,14 @@ public:
}
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
unsigned int diff = binding - pads[port][slot].ffBindings;
if (diff < (unsigned int)pads[port][slot].numFFBindings) {
int padtype = config.padConfigs[port][slot].type;
unsigned int diff = binding - pads[port][slot][padtype].ffBindings;
if (diff < (unsigned int)pads[port][slot][padtype].numFFBindings) {
index += diff;
port = 2;
break;
}
index += pads[port][slot].numFFBindings;
index += pads[port][slot][padtype].numFFBindings;
}
}
IDirectInputEffect *die = diEffects[index].die;
@ -269,10 +271,11 @@ public:
i = 0;
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
int padtype = config.padConfigs[port][slot].type;
int subIndex = i;
for (int j = 0; j < pads[port][slot].numFFBindings; j++) {
for (int j = 0; j < pads[port][slot][padtype].numFFBindings; j++) {
ForceFeedbackBinding *b = 0;
b = &pads[port][slot].ffBindings[i - subIndex];
b = &pads[port][slot][padtype].ffBindings[i - subIndex];
ForceFeedbackEffectType *eff = ffEffectTypes + b->effectIndex;
GUID guid;
if (!StringToGUID(&guid, eff->effectID))
@ -369,7 +372,8 @@ public:
int count = 0;
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
count += pads[port][slot].numFFBindings;
int padtype = config.padConfigs[port][slot].type;
count += pads[port][slot][padtype].numFFBindings;
}
}
return count;

View File

@ -17,6 +17,7 @@
#include "Global.h"
#include "InputManager.h"
#include "Config.h"
#include "usb.h"
#include "HidDevice.h"
@ -421,9 +422,10 @@ public:
vibration[0] = vibration[1] = 0;
for (int p = 0; p < 2; p++) {
for (int s = 0; s < 4; s++) {
for (int i = 0; i < pads[p][s].numFFBindings; i++) {
int padtype = config.padConfigs[p][s].type;
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.
ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i];
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);
}
@ -436,11 +438,11 @@ public:
void SetEffect(ForceFeedbackBinding *binding, unsigned char force)
{
PadBindings pBackup = pads[0][0];
pads[0][0].ffBindings = binding;
pads[0][0].numFFBindings = 1;
PadBindings pBackup = pads[0][0][0];
pads[0][0][0].ffBindings = binding;
pads[0][0][0].numFFBindings = 1;
SetEffects(0, 0, binding->motor, 255);
pads[0][0] = pBackup;
pads[0][0][0] = pBackup;
}
void Deactivate()

View File

@ -18,6 +18,7 @@
#include "Global.h"
#include "InputManager.h"
#include "KeyboardQueue.h"
#include "Config.h"
InputDeviceManager *dm = 0;
@ -94,11 +95,13 @@ Device::~Device()
int i;
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
free(pads[port][slot].bindings);
for (i = 0; i < pads[port][slot].numFFBindings; i++) {
free(pads[port][slot].ffBindings[i].axes);
for (int padtype = 0; padtype < numPadTypes; padtype++) {
free(pads[port][slot][padtype].bindings);
for (i = 0; i < pads[port][slot][padtype].numFFBindings; i++) {
free(pads[port][slot][padtype].ffBindings[i].axes);
}
free(pads[port][slot][padtype].ffBindings);
}
free(pads[port][slot].ffBindings);
}
}
free(virtualControls);
@ -145,11 +148,13 @@ void Device::AddFFAxis(const wchar_t *displayName, int id)
int bindingsExist = 0;
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
for (int i = 0; i < pads[port][slot].numFFBindings; i++) {
ForceFeedbackBinding *b = pads[port][slot].ffBindings + i;
b->axes = (AxisEffectInfo *)realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes));
memset(b->axes + (numFFAxes - 1), 0, sizeof(AxisEffectInfo));
bindingsExist = 1;
for (int padtype = 0; padtype < numPadTypes; padtype++) {
for (int i = 0; i < pads[port][slot][padtype].numFFBindings; i++) {
ForceFeedbackBinding *b = pads[port][slot][padtype].ffBindings + i;
b->axes = (AxisEffectInfo *)realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes));
memset(b->axes + (numFFAxes - 1), 0, sizeof(AxisEffectInfo));
bindingsExist = 1;
}
}
}
}
@ -319,8 +324,9 @@ PhysicalControl *Device::AddPhysicalControl(ControlType type, unsigned short id,
void Device::SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force)
{
for (int i = 0; i < pads[port][slot].numFFBindings; i++) {
ForceFeedbackBinding *binding = pads[port][slot].ffBindings + i;
int padtype = config.padConfigs[port][slot].type;
for (int i = 0; i < pads[port][slot][padtype].numFFBindings; i++) {
ForceFeedbackBinding *binding = pads[port][slot][padtype].ffBindings + i;
if (binding->motor == motor) {
SetEffect(binding, force);
}
@ -545,9 +551,11 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices)
old = oldDevices[i];
for (port = 0; port < 2; port++) {
for (slot = 0; slot < 4; slot++) {
if (old->pads[port][slot].numBindings + old->pads[port][slot].numFFBindings) {
// Means that there are bindings.
oldMatches[i] = -1;
for (int padtype = 0; padtype < numPadTypes; padtype++) {
if (old->pads[port][slot][padtype].numBindings + old->pads[port][slot][padtype].numFFBindings) {
// Means that there are bindings.
oldMatches[i] = -1;
}
}
}
}
@ -603,36 +611,38 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices)
dev = devices[oldMatches[i]];
for (port = 0; port < 2; port++) {
for (slot = 0; slot < 4; slot++) {
if (old->pads[port][slot].numBindings) {
dev->pads[port][slot].bindings = (Binding *)malloc(old->pads[port][slot].numBindings * sizeof(Binding));
for (int j = 0; j < old->pads[port][slot].numBindings; j++) {
Binding *bo = old->pads[port][slot].bindings + j;
Binding *bn = dev->pads[port][slot].bindings + dev->pads[port][slot].numBindings;
VirtualControl *cn = dev->GetVirtualControl(old->virtualControls[bo->controlIndex].uid);
if (cn) {
*bn = *bo;
bn->controlIndex = cn - dev->virtualControls;
dev->pads[port][slot].numBindings++;
for (int padtype = 0; padtype < numPadTypes; padtype++) {
if (old->pads[port][slot][padtype].numBindings) {
dev->pads[port][slot][padtype].bindings = (Binding *)malloc(old->pads[port][slot][padtype].numBindings * sizeof(Binding));
for (int j = 0; j < old->pads[port][slot][padtype].numBindings; j++) {
Binding *bo = old->pads[port][slot][padtype].bindings + j;
Binding *bn = dev->pads[port][slot][padtype].bindings + dev->pads[port][slot][padtype].numBindings;
VirtualControl *cn = dev->GetVirtualControl(old->virtualControls[bo->controlIndex].uid);
if (cn) {
*bn = *bo;
bn->controlIndex = cn - dev->virtualControls;
dev->pads[port][slot][padtype].numBindings++;
}
}
}
}
if (old->pads[port][slot].numFFBindings) {
dev->pads[port][slot].ffBindings = (ForceFeedbackBinding *)malloc(old->pads[port][slot].numFFBindings * sizeof(ForceFeedbackBinding));
for (int j = 0; j < old->pads[port][slot].numFFBindings; j++) {
ForceFeedbackBinding *bo = old->pads[port][slot].ffBindings + j;
ForceFeedbackBinding *bn = dev->pads[port][slot].ffBindings + dev->pads[port][slot].numFFBindings;
ForceFeedbackEffectType *en = dev->GetForcefeedbackEffect(old->ffEffectTypes[bo->effectIndex].effectID);
if (en) {
*bn = *bo;
bn->effectIndex = en - dev->ffEffectTypes;
bn->axes = (AxisEffectInfo *)calloc(dev->numFFAxes, sizeof(AxisEffectInfo));
for (int k = 0; k < old->numFFAxes; k++) {
ForceFeedbackAxis *newAxis = dev->GetForceFeedbackAxis(old->ffAxes[k].id);
if (newAxis) {
bn->axes[newAxis - dev->ffAxes] = bo->axes[k];
if (old->pads[port][slot][padtype].numFFBindings) {
dev->pads[port][slot][padtype].ffBindings = (ForceFeedbackBinding *)malloc(old->pads[port][slot][padtype].numFFBindings * sizeof(ForceFeedbackBinding));
for (int j = 0; j < old->pads[port][slot][padtype].numFFBindings; j++) {
ForceFeedbackBinding *bo = old->pads[port][slot][padtype].ffBindings + j;
ForceFeedbackBinding *bn = dev->pads[port][slot][padtype].ffBindings + dev->pads[port][slot][padtype].numFFBindings;
ForceFeedbackEffectType *en = dev->GetForcefeedbackEffect(old->ffEffectTypes[bo->effectIndex].effectID);
if (en) {
*bn = *bo;
bn->effectIndex = en - dev->ffEffectTypes;
bn->axes = (AxisEffectInfo *)calloc(dev->numFFAxes, sizeof(AxisEffectInfo));
for (int k = 0; k < old->numFFAxes; k++) {
ForceFeedbackAxis *newAxis = dev->GetForceFeedbackAxis(old->ffAxes[k].id);
if (newAxis) {
bn->axes[newAxis - dev->ffAxes] = bo->axes[k];
}
}
dev->pads[port][slot][padtype].numFFBindings++;
}
dev->pads[port][slot].numFFBindings++;
}
}
}

View File

@ -32,6 +32,14 @@
* Still more effort than it's worth to port to Linux, however.
*/
enum PadType {
DisabledPad,
Dualshock2Pad,
GuitarPad,
PopnPad,
numPadTypes // total number of PadTypes. Add new PadType above this line.
};
// 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
// 4 virtual ones.
@ -259,7 +267,7 @@ public:
};
};
PadBindings pads[2][4];
PadBindings pads[2][4][numPadTypes];
// 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

View File

@ -271,7 +271,7 @@ void UpdateEnabledDevices(int updateList = 0)
// Figure out which pads I'm getting input for.
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
if (slot && !config.multitap[port]) {
if (slot > 0 && !config.multitap[port]) {
pads[port][slot].enabled = 0;
} else {
pads[port][slot].enabled = pads[port][slot].initialized && config.padConfigs[port][slot].type != DisabledPad;
@ -290,7 +290,7 @@ void UpdateEnabledDevices(int updateList = 0)
// Disable ignore keyboard if don't have focus or there are no keys to ignore.
if (dev->api == IGNORE_KEYBOARD) {
if ((config.keyboardApi == NO_API || !dev->pads[0][0].numBindings) || !activeWindow) {
if ((config.keyboardApi == NO_API || !dev->pads[0][0][0].numBindings) || !activeWindow) {
dm->DisableDevice(i);
}
continue;
@ -311,8 +311,9 @@ void UpdateEnabledDevices(int updateList = 0)
int numActiveBindings = 0;
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
int padtype = config.padConfigs[port][slot].type;
if (pads[port][slot].enabled) {
numActiveBindings += dev->pads[port][slot].numBindings + dev->pads[port][slot].numFFBindings;
numActiveBindings += dev->pads[port][slot][padtype].numBindings + dev->pads[port][slot][padtype].numFFBindings;
}
}
}
@ -537,10 +538,11 @@ void Update(unsigned int port, unsigned int slot)
continue;
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
if (config.padConfigs[port][slot].type == DisabledPad || !pads[port][slot].initialized)
int padtype = config.padConfigs[port][slot].type;
if (padtype == DisabledPad || !pads[port][slot].initialized)
continue;
for (int j = 0; j < dev->pads[port][slot].numBindings; j++) {
Binding *b = dev->pads[port][slot].bindings + j;
for (int j = 0; j < dev->pads[port][slot][padtype].numBindings; j++) {
Binding *b = dev->pads[port][slot][padtype].bindings + j;
int cmd = b->command;
int state = dev->virtualControlState[b->controlIndex];
if (!(turbo & b->turbo)) {
@ -833,9 +835,8 @@ s32 CALLBACK PADinit(u32 flags)
port--;
for (int i = 0; i < 4; i++) {
ResetPad(port, i);
}
for (int slot = 0; slot < 4; slot++)
ResetPad(port, slot);
slots[port] = 0;
portInitialized[port] = 1;

View File

@ -81,29 +81,29 @@ struct GeneralSettingsBool
};
// XXX: I try to remove only gui stuff
void DeleteBinding(int port, int slot, Device *dev, Binding *b)
void DeleteBinding(int port, int slot, int padtype, Device *dev, Binding *b)
{
fprintf(stderr, "delete binding %d:%d\n", port, slot);
Binding *bindings = dev->pads[port][slot].bindings;
Binding *bindings = dev->pads[port][slot][padtype].bindings;
int i = b - bindings;
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot].numBindings - i - 1));
dev->pads[port][slot].numBindings--;
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot][padtype].numBindings - i - 1));
dev->pads[port][slot][padtype].numBindings--;
}
void DeleteBinding(int port, int slot, Device *dev, ForceFeedbackBinding *b)
{
ForceFeedbackBinding *bindings = dev->pads[port][slot].ffBindings;
int padtype = config.padConfigs[port][slot].type;
ForceFeedbackBinding *bindings = dev->pads[port][slot][padtype].ffBindings;
int i = b - bindings;
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot].numFFBindings - i - 1));
dev->pads[port][slot].numFFBindings--;
memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot][padtype].numFFBindings - i - 1));
dev->pads[port][slot][padtype].numFFBindings--;
}
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo, int deadZone)
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, unsigned int padtype, int command, int sensitivity, int turbo, int deadZone)
{
// Checks needed because I use this directly when loading bindings.
if (port > 1 || slot > 3) {
if (port > 1 || slot > 3 || padtype >= numPadTypes)
return -1;
}
if (!sensitivity)
sensitivity = BASE_SENSITIVITY;
if ((uid >> 16) & (PSHBTN | TGLBTN)) {
@ -125,7 +125,7 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int s
// Add before deleting. Means I won't scroll up one line when scrolled down to bottom.
int controlIndex = c - dev->virtualControls;
int index = 0;
PadBindings *p = dev->pads[port] + slot;
PadBindings *p = dev->pads[port][slot] + padtype;
p->bindings = (Binding *)realloc(p->bindings, (p->numBindings + 1) * sizeof(Binding));
for (index = p->numBindings; index > 0; index--) {
if (p->bindings[index - 1].controlIndex < controlIndex)
@ -167,20 +167,22 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int s
newBindingIndex--;
//count --;
}
DeleteBinding(port, slot, dev, b);
DeleteBinding(port, slot, padtype, dev, b);
}
if (!config.multipleBinding) {
for (int port2 = 0; port2 < 2; port2++) {
for (int slot2 = 0; slot2 < 4; slot2++) {
if (port2 == (int)port && slot2 == (int)slot)
continue;
PadBindings *p = dev->pads[port2] + slot2;
for (int i = 0; i < p->numBindings; i++) {
Binding *b = p->bindings + i;
int uid2 = dev->virtualControls[b->controlIndex].uid;
if (b->controlIndex == controlIndex || (!((uid2 ^ uid) & 0xFFFFFF) && ((uid | uid2) & (UID_POV | UID_AXIS)))) {
DeleteBinding(port2, slot2, dev, b);
i--;
for (int padtype2 = 0; padtype2 < numPadTypes; padtype2++) {
PadBindings *p = dev->pads[port2][slot2] + padtype2;
for (int i = 0; i < p->numBindings; i++) {
Binding *b = p->bindings + i;
int uid2 = dev->virtualControls[b->controlIndex].uid;
if (b->controlIndex == controlIndex || (!((uid2 ^ uid) & 0xFFFFFF) && ((uid | uid2) & (UID_POV | UID_AXIS)))) {
DeleteBinding(port2, slot2, padtype2, dev, b);
i--;
}
}
}
}
@ -270,27 +272,29 @@ int SaveSettings(wchar_t *file = 0)
int bindingCount = 0;
for (int port = 0; port < 2; port++) {
for (int slot = 0; slot < 4; slot++) {
for (int j = 0; j < dev->pads[port][slot].numBindings; j++) {
Binding *b = dev->pads[port][slot].bindings + j;
VirtualControl *c = &dev->virtualControls[b->controlIndex];
wsprintfW(temp, L"Binding %i", bindingCount++);
wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i, %i, %i", c->uid, port, b->command, b->sensitivity, b->turbo, slot, b->deadZone);
cfg.WriteStr(id, temp, temp2);
}
for (int j = 0; j < dev->pads[port][slot].numFFBindings; j++) {
ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings + j;
ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex];
wsprintfW(temp, L"FF Binding %i", ffBindingCount++);
wsprintfW(temp2, L"%s %i, %i, %i", eff->effectID, port, b->motor, slot);
for (int k = 0; k < dev->numFFAxes; k++) {
ForceFeedbackAxis *axis = dev->ffAxes + k;
AxisEffectInfo *info = b->axes + k;
//wsprintfW(wcschr(temp2,0), L", %i, %i", axis->id, info->force);
// Not secure because I'm too lazy to compute the remaining size
wprintf(wcschr(temp2, 0), L", %i, %i", axis->id, info->force);
for (int padtype = 0; padtype < numPadTypes; padtype++) {
for (int j = 0; j < dev->pads[port][slot][padtype].numBindings; j++) {
Binding *b = dev->pads[port][slot][padtype].bindings + j;
VirtualControl *c = &dev->virtualControls[b->controlIndex];
wsprintfW(temp, L"Binding %i", bindingCount++);
wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i, %i, %i, %i", c->uid, port, b->command, b->sensitivity, b->turbo, slot, b->deadZone, padtype);
cfg.WriteStr(id, temp, temp2);
}
for (int j = 0; j < dev->pads[port][slot][padtype].numFFBindings; j++) {
ForceFeedbackBinding *b = dev->pads[port][slot][padtype].ffBindings + j;
ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex];
wsprintfW(temp, L"FF Binding %i", ffBindingCount++);
wsprintfW(temp2, L"%s %i, %i, %i, %i", eff->effectID, port, b->motor, slot, padtype);
for (int k = 0; k < dev->numFFAxes; k++) {
ForceFeedbackAxis *axis = dev->ffAxes + k;
AxisEffectInfo *info = b->axes + k;
//wsprintfW(wcschr(temp2,0), L", %i, %i", axis->id, info->force);
// Not secure because I'm too lazy to compute the remaining size
wprintf(wcschr(temp2, 0), L", %i, %i", axis->id, info->force);
}
cfg.WriteStr(id, temp, temp2);
}
cfg.WriteStr(id, temp, temp2);
}
}
}
@ -334,6 +338,7 @@ int LoadSettings(int force, wchar_t *file)
}
}
bool oldIni = false;
int i = 0;
int multipleBinding = config.multipleBinding;
// Disabling multiple binding only prevents new multiple bindings.
@ -374,7 +379,7 @@ int LoadSettings(int force, wchar_t *file)
}
last = 1;
unsigned int uid;
int port, command, sensitivity, turbo, slot = 0, deadZone = 0;
int port, command, sensitivity, turbo, slot = 0, deadZone = 0, padtype = 0;
int w = 0;
char string[1000];
while (temp2[w]) {
@ -382,13 +387,21 @@ int LoadSettings(int force, wchar_t *file)
w++;
}
string[w] = 0;
int len = sscanf(string, " %u , %i , %i , %i , %i , %i , %i", &uid, &port, &command, &sensitivity, &turbo, &slot, &deadZone);
int len = sscanf(string, " %u , %i , %i , %i , %i , %i , %i , %i", &uid, &port, &command, &sensitivity, &turbo, &slot, &deadZone, &padtype);
if (len >= 5 && type) {
VirtualControl *c = dev->GetVirtualControl(uid);
if (!c)
c = dev->AddVirtualControl(uid, -1);
if (c) {
BindCommand(dev, uid, port, slot, command, sensitivity, turbo, deadZone);
if (len < 8) { // If ini file is imported from older version, make sure bindings aren't applied to "Unplugged" padtype.
oldIni = true;
if (config.padConfigs[port][slot].type != 0) {
padtype = config.padConfigs[port][slot].type;
} else {
padtype = 1;
}
}
BindCommand(dev, uid, port, slot, padtype, command, sensitivity, turbo, deadZone);
}
}
}
@ -404,7 +417,7 @@ int LoadSettings(int force, wchar_t *file)
continue;
}
last = 1;
int port, slot, motor;
int port, slot, motor, padtype;
int w = 0;
char string[1000];
char effect[1000];
@ -415,8 +428,18 @@ int LoadSettings(int force, wchar_t *file)
string[w] = 0;
// wcstok not in ntdll. More effore than its worth to shave off
// whitespace without it.
if (sscanf(string, " %s %i , %i , %i", effect, &port, &motor, &slot) == 4) {
char *s = strchr(strchr(strchr(string, ',') + 1, ',') + 1, ',');
if (sscanf(string, " %20s %i , %i , %i , %i", effect, &port, &motor, &slot, &padtype) == 5) {
char *s;
if (oldIni) { // Make sure bindings aren't applied to "Unplugged" padtype and FF settings are read from old location.
if (config.padConfigs[port][slot].type != 0) {
padtype = config.padConfigs[port][slot].type;
} else {
padtype = 1;
}
s = strchr(strchr(strchr(string, ',') + 1, ',') + 1, ',');
} else {
s = strchr(strchr(strchr(strchr(string, ',') + 1, ',') + 1, ',') + 1, ',');
}
if (!s)
continue;
s++;

View File

@ -21,6 +21,7 @@
#include "VKey.h"
#include "InputManager.h"
#include "XInputEnum.h"
#include "Config.h"
// Extra enum
#define XINPUT_GAMEPAD_GUIDE 0x0400
@ -209,9 +210,10 @@ public:
int newVibration[2] = {0, 0};
for (int p = 0; p < 2; p++) {
for (int s = 0; s < 4; s++) {
for (int i = 0; i < pads[p][s].numFFBindings; i++) {
int padtype = config.padConfigs[p][s].type;
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.
ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i];
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);
}
@ -235,11 +237,11 @@ public:
void SetEffect(ForceFeedbackBinding *binding, unsigned char force)
{
PadBindings pBackup = pads[0][0];
pads[0][0].ffBindings = binding;
pads[0][0].numFFBindings = 1;
PadBindings pBackup = pads[0][0][0];
pads[0][0][0].ffBindings = binding;
pads[0][0][0].numFFBindings = 1;
SetEffects(0, 0, binding->motor, 255);
pads[0][0] = pBackup;
pads[0][0][0] = pBackup;
}
void Deactivate()