LilyPad: Lots of new code that (ideally) makes absolutely no difference. And a fix for saving rumble settings in PADfreeze.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@794 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
mattmenke 2009-03-15 15:00:22 +00:00
parent 3f87ae7078
commit 0c95bbc9fd
10 changed files with 716 additions and 595 deletions

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,20 @@
extern u8 ps2e;
enum PadType {
DisabledPad,
Dualshock2Pad,
GuitarPad
};
struct PadConfig {
PadType type;
u8 autoAnalog;
};
struct GeneralConfig {
public:
u8 disablePad[2];
PadConfig padConfigs[2][4];
u8 mouseUnfocus;
u8 disableScreenSaver;
@ -32,9 +43,6 @@ public:
u8 GSThreadUpdates;
u8 escapeFullscreenHack;
u8 guitar[2];
u8 AutoAnalog[2];
u8 saveStateTitle;
u8 vistaVolume;

View File

@ -98,9 +98,17 @@ public:
}
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {
unsigned int index = binding - pads[0].ffBindings;
if (index >= (unsigned int)pads[0].numFFBindings) {
index = pads[0].numFFBindings + (binding - pads[1].ffBindings);
int index = 0;
for (int port=0; port<2; port++) {
for (int slot=0; slot<4; slot++) {
unsigned int diff = binding - pads[port][slot].ffBindings;
if (diff < (unsigned int)pads[port][slot].numFFBindings) {
index += diff;
port = 2;
break;
}
index += pads[port][slot].numFFBindings;
}
}
IDirectInputEffect *die = diEffects[index].die;
if (die) {
@ -139,7 +147,7 @@ public:
}
int Activate(void *d) {
int i, j;
int i;
IDirectInput8 *di8 = GetDirectInput();
Deactivate();
if (!di8) return 0;
@ -211,74 +219,78 @@ public:
return 0;
}
AllocState();
diEffects = (DI8Effect*) calloc(pads[0].numFFBindings + pads[1].numFFBindings, sizeof(DI8Effect));
for (i=0; i<pads[0].numFFBindings + pads[1].numFFBindings; i++) {
ForceFeedbackBinding *b = 0;
if (i >= pads[0].numFFBindings) {
b = &pads[1].ffBindings[i-pads[0].numFFBindings];
}
else
b = &pads[0].ffBindings[i];
ForceFeedbackEffectType *eff = ffEffectTypes + b->effectIndex;
GUID guid;
if (!StringToGUID(&guid, eff->effectID)) continue;
int count = GetFFBindingCount();
diEffects = (DI8Effect*) calloc(count, sizeof(DI8Effect));
i = 0;
for (int port=0; port<2; port++) {
for (int slot=0; slot<4; slot++) {
int subIndex = i;
for (int j=0; j<pads[port][slot].numFFBindings; j++) {
ForceFeedbackBinding *b = 0;
b = &pads[port][slot].ffBindings[i-subIndex];
ForceFeedbackEffectType *eff = ffEffectTypes + b->effectIndex;
GUID guid;
if (!StringToGUID(&guid, eff->effectID)) continue;
DIEFFECT dieffect;
memset(&dieffect, 0, sizeof(dieffect));
dieffect.dwSize = sizeof(dieffect);
dieffect.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTIDS;
dieffect.dwDuration = 2000000;
dieffect.dwGain = 10000;
dieffect.dwTriggerButton = DIEB_NOTRIGGER;
union {
DIPERIODIC pediodic;
DIRAMPFORCE ramp;
DICONSTANTFORCE constant;
} stuff = {0,0,0,0};
DIEFFECT dieffect;
memset(&dieffect, 0, sizeof(dieffect));
dieffect.dwSize = sizeof(dieffect);
dieffect.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTIDS;
dieffect.dwDuration = 2000000;
dieffect.dwGain = 10000;
dieffect.dwTriggerButton = DIEB_NOTRIGGER;
union {
DIPERIODIC pediodic;
DIRAMPFORCE ramp;
DICONSTANTFORCE constant;
} stuff = {0,0,0,0};
if (eff->type == EFFECT_CONSTANT) {
dieffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
}
else if (eff->type == EFFECT_PERIODIC) {
dieffect.cbTypeSpecificParams = sizeof(DIPERIODIC);
}
else if (eff->type == EFFECT_RAMP) {
dieffect.cbTypeSpecificParams = sizeof(DIRAMPFORCE);
}
dieffect.lpvTypeSpecificParams = &stuff;
int maxForce = 0;
int numAxes = 0;
int *axes = (int*) malloc(sizeof(int) * 3 * numFFAxes);
DWORD *axisIDs = (DWORD*)(axes + numFFAxes);
LONG *dirList = (LONG*)(axisIDs + numFFAxes);
dieffect.rgdwAxes = axisIDs;
dieffect.rglDirection = dirList;
for (j=0; j<numFFAxes; j++) {
if (b->axes[j].force) {
int force = abs(b->axes[j].force);
if (force > maxForce) {
maxForce = force;
if (eff->type == EFFECT_CONSTANT) {
dieffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
}
axes[numAxes] = j;
axisIDs[numAxes] = ffAxes[j].id;
dirList[numAxes] = b->axes[j].force;
numAxes++;
else if (eff->type == EFFECT_PERIODIC) {
dieffect.cbTypeSpecificParams = sizeof(DIPERIODIC);
}
else if (eff->type == EFFECT_RAMP) {
dieffect.cbTypeSpecificParams = sizeof(DIRAMPFORCE);
}
dieffect.lpvTypeSpecificParams = &stuff;
int maxForce = 0;
int numAxes = 0;
int *axes = (int*) malloc(sizeof(int) * 3 * numFFAxes);
DWORD *axisIDs = (DWORD*)(axes + numFFAxes);
LONG *dirList = (LONG*)(axisIDs + numFFAxes);
dieffect.rgdwAxes = axisIDs;
dieffect.rglDirection = dirList;
for (int k=0; k<numFFAxes; k++) {
if (b->axes[k].force) {
int force = abs(b->axes[k].force);
if (force > maxForce) {
maxForce = force;
}
axes[numAxes] = k;
axisIDs[numAxes] = ffAxes[k].id;
dirList[numAxes] = b->axes[k].force;
numAxes++;
}
}
if (!numAxes) {
free(axes);
continue;
}
dieffect.cAxes = numAxes;
diEffects[i].scale = maxForce;
if (!SUCCEEDED(did->CreateEffect(guid, &dieffect, &diEffects[i].die, 0))) {
diEffects[i].die = 0;
diEffects[i].scale = 0;
}
free(axes);
axes = 0;
i++;
}
}
if (!numAxes) {
free(axes);
continue;
}
dieffect.cAxes = numAxes;
diEffects[i].scale = maxForce;
if (!SUCCEEDED(did->CreateEffect(guid, &dieffect, &diEffects[i].die, 0))) {
diEffects[i].die = 0;
diEffects[i].scale = 0;
}
free(axes);
axes = 0;
}
active = 1;
return 1;
@ -306,10 +318,21 @@ public:
return 1;
}
int GetFFBindingCount() {
int count = 0;
for (int port = 0; port<2; port++) {
for (int slot = 0; slot<4; slot++) {
count += pads[port][slot].numFFBindings;
}
}
return count;
}
void Deactivate() {
FreeState();
if (diEffects) {
for (int i=0; i<pads[0].numFFBindings + pads[1].numFFBindings; i++) {
int count = GetFFBindingCount();
for (int i=0; i<count; i++) {
if (diEffects[i].die) {
diEffects[i].die->Stop();
diEffects[i].die->Release();

View File

@ -67,12 +67,14 @@ Device::~Device() {
// Generally called by deactivate, but just in case...
FreeState();
int i;
for (int pad=0; pad<2; pad++) {
free(pads[pad].bindings);
for (i=0; i<pads[pad].numFFBindings; i++) {
free(pads[pad].ffBindings[i].axes);
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);
}
free(pads[port][slot].ffBindings);
}
free(pads[pad].ffBindings);
}
free(virtualControls);
@ -112,11 +114,13 @@ void Device::AddFFAxis(const wchar_t *displayName, int id) {
ffAxes[numFFAxes].id = id;
ffAxes[numFFAxes].displayName = wcsdup(displayName);
numFFAxes++;
for (int pad=0; pad<2; pad++) {
for (int i=0; i<pads[pad].numFFBindings; i++) {
ForceFeedbackBinding *b = pads[pad].ffBindings+i;
b->axes = (AxisEffectInfo*) realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes));
memset(b->axes + (numFFAxes-1), 0, sizeof(AxisEffectInfo));
for (int port=0; port<2; port++) {
for (int slot=0; slot<4; slot++) {
for (int i=0; i<pads[port][slot].numFFBindings; i++) {
ForceFeedbackBinding *b = pads[port][slot].ffBindings+i;
b->axes = (AxisEffectInfo*) realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes));
memset(b->axes + (numFFAxes-1), 0, sizeof(AxisEffectInfo));
}
}
}
}
@ -254,9 +258,9 @@ PhysicalControl *Device::AddPhysicalControl(ControlType type, unsigned short id,
return control;
}
void Device::SetEffects(unsigned char pad, unsigned char motor, unsigned char force) {
for (int i=0; i<pads[pad].numFFBindings; i++) {
ForceFeedbackBinding *binding = pads[pad].ffBindings+i;
void Device::SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) {
for (int i=0; i<pads[port][slot].numFFBindings; i++) {
ForceFeedbackBinding *binding = pads[port][slot].ffBindings+i;
if (binding->motor == motor) {
SetEffect(binding, force);
}
@ -451,7 +455,7 @@ ForceFeedbackAxis *Device::GetForceFeedbackAxis(int id) {
void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
int *oldMatches = (int*) malloc(sizeof(int) * numOldDevices);
int *matches = (int*) malloc(sizeof(int) * numDevices);
int i, j, pad;
int i, j, port, slot;
Device *old, *dev;
for (i=0; i<numDevices; i++) {
matches[i] = -1;
@ -459,10 +463,12 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
for (i=0; i<numOldDevices; i++) {
oldMatches[i] = -2;
old = oldDevices[i];
for (pad=0; pad<2; pad++) {
if (old->pads[pad].numBindings + old->pads[pad].numFFBindings) {
// Means that there are bindings.
oldMatches[i] = -1;
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;
}
}
}
}
@ -514,37 +520,39 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
}
else {
dev = devices[oldMatches[i]];
for (pad=0; pad<2; pad++) {
if (old->pads[pad].numBindings) {
dev->pads[pad].bindings = (Binding*) malloc(old->pads[pad].numBindings * sizeof(Binding));
for (int j=0; j<old->pads[pad].numBindings; j++) {
Binding *bo = old->pads[pad].bindings + j;
Binding *bn = dev->pads[pad].bindings + dev->pads[pad].numBindings;
VirtualControl *cn = dev->GetVirtualControl(old->virtualControls[bo->controlIndex].uid);
if (cn) {
*bn = *bo;
bn->controlIndex = cn - dev->virtualControls;
dev->pads[pad].numBindings++;
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++;
}
}
}
}
if (old->pads[pad].numFFBindings) {
dev->pads[pad].ffBindings = (ForceFeedbackBinding*) malloc(old->pads[pad].numFFBindings * sizeof(ForceFeedbackBinding));
for (int j=0; j<old->pads[pad].numFFBindings; j++) {
ForceFeedbackBinding *bo = old->pads[pad].ffBindings + j;
ForceFeedbackBinding *bn = dev->pads[pad].ffBindings + dev->pads[pad].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].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];
}
}
dev->pads[port][slot].numFFBindings++;
}
dev->pads[pad].numFFBindings++;
}
}
}
@ -555,11 +563,11 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
free(matches);
}
void InputDeviceManager::SetEffect(unsigned char pad, unsigned char motor, unsigned char force) {
void InputDeviceManager::SetEffect(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) {
for (int i=0; i<numDevices; i++) {
Device *dev = devices[i];
if (dev->enabled && dev->numFFEffectTypes) {
dev->SetEffects(pad, motor, force);
dev->SetEffects(port, slot, motor, force);
}
}
}

View File

@ -194,7 +194,7 @@ public:
};
};
PadBindings pads[2];
PadBindings pads[2][4];
// 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
@ -267,7 +267,7 @@ public:
// Note: Only used externally for binding, so if override the other one, can assume
// all other forces are currently 0.
inline virtual void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {}
inline virtual void SetEffects(unsigned char pad, unsigned char motor, unsigned char force);
inline virtual void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force);
// Called after reading. Basically calls FlipState().
// Some device types (Those that don't incrementally update)
@ -303,7 +303,7 @@ public:
// Called after reading state, after Update().
void PostRead();
void SetEffect(unsigned char pad, 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.
// void GetInput(void *v);

View File

@ -87,8 +87,8 @@ LRESULT CALLBACK IgnoreKeyboardHook(int code, WPARAM wParam, LPARAM lParam) {
if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) {
KBDLLHOOKSTRUCT* key = (KBDLLHOOKSTRUCT*) lParam;
if (key->vkCode < 256) {
for (int i=0; i<ikhd->pads[0].numBindings; i++) {
if (ikhd->pads[0].bindings[i].controlIndex == key->vkCode) {
for (int i=0; i<ikhd->pads[0][0].numBindings; i++) {
if (ikhd->pads[0][0].bindings[i].controlIndex == key->vkCode) {
return 1;
}
}

View File

@ -106,28 +106,38 @@ struct ButtonSum {
Stick sticks[3];
};
class Pad {
struct PadFreezeData {
// Digital / Analog / Full Analog (aka DS2 Native)
u8 mode;
u8 modeLock;
// In config mode
u8 config;
u8 vibrate[8];
u8 umask[2];
};
class Pad : public PadFreezeData {
public:
ButtonSum sum, lockedSum;
int lockedState;
u8 vibrate[8];
u8 umask[2];
u8 vibrateI[2];
u8 vibrateVal[2];
// Digital / Analog / Full Analog (aka DS2 Native)
u8 mode;
u8 modeLock;
// In config mode
u8 config;
// Used to keep track of which pads I'm running.
// Note that initialized pads *can* be disabled.
// I keep track of state of non-disabled non-initialized
// pads, but should never be asked for their state.
u8 initialized;
} pads[2];
} pads[2][4];
// Active slots for each port.
int slots[2];
// Which ports we're running on.
int portInitialized[2];
// Force value to be from 0 to 255.
u8 Cap (int i) {
@ -149,9 +159,15 @@ void UpdateEnabledDevices(int updateList = 0) {
// Enable all devices I might want. Can ignore the rest.
RefreshEnabledDevices(updateList);
// Figure out which pads I'm getting input for.
int padsEnabled[2] = {
pads[0].initialized && !config.disablePad[0],
pads[1].initialized && !config.disablePad[1]
int padsEnabled[2][4] = {
{pads[0][0].initialized && config.padConfigs[0][0].type != DisabledPad,
pads[0][1].initialized && config.padConfigs[0][1].type != DisabledPad,
pads[0][2].initialized && config.padConfigs[0][2].type != DisabledPad,
pads[0][3].initialized && config.padConfigs[0][3].type != DisabledPad},
{pads[1][0].initialized && config.padConfigs[1][0].type != DisabledPad,
pads[1][1].initialized && config.padConfigs[1][1].type != DisabledPad,
pads[1][2].initialized && config.padConfigs[1][2].type != DisabledPad,
pads[1][3].initialized && config.padConfigs[1][3].type != DisabledPad}
};
for (int i=0; i<dm->numDevices; i++) {
Device *dev = dm->devices[i];
@ -164,7 +180,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.vistaVolume && (config.keyboardApi == NO_API || !dev->pads[0].numBindings)) || !activeWindow) {
if ((!config.vistaVolume && (config.keyboardApi == NO_API || !dev->pads[0][0].numBindings)) || !activeWindow) {
dm->DisableDevice(i);
}
continue;
@ -181,9 +197,11 @@ void UpdateEnabledDevices(int updateList = 0) {
else if (!activeWindow && !config.background) dm->DisableDevice(i);
else {
int numActiveBindings = 0;
for (int pad=0; pad<2; pad++) {
if (padsEnabled[pad]) {
numActiveBindings += dev->pads[pad].numBindings + dev->pads[pad].numFFBindings;
for (int port=0; port<2; port++) {
for (int slot=0; slot<4; slot++) {
if (padsEnabled[port][slot]) {
numActiveBindings += dev->pads[port][slot].numBindings + dev->pads[port][slot].numFFBindings;
}
}
}
if (!numActiveBindings)
@ -297,7 +315,6 @@ void CapSum(ButtonSum *sum) {
// key press info requests.
int summed[3] = {0, 0, 0};
int lockStateChanged[2] = {0,0};
#define LOCK_DIRECTION 2
#define LOCK_BUTTONS 4
#define LOCK_BOTH 1
@ -310,9 +327,13 @@ void Update(int pad) {
return;
}
int i;
ButtonSum s[2];
s[0] = pads[0].lockedSum;
s[1] = pads[1].lockedSum;
ButtonSum s[2][4];
u8 lockStateChanged[2][4];
memset(lockStateChanged, 0, sizeof(lockStateChanged));
for (i=0; i<8; i++) {
s[i&1][i>>1] = pads[i&1][i>>1].lockedSum;
}
InitInfo info = {
0, hWnd, hWnd, 0
};
@ -328,36 +349,38 @@ void Update(int pad) {
// Skip both disabled devices and inactive enabled devices.
// Shouldn't be any of the latter, in general, but just in case...
if (!dev->virtualControlState) continue;
for (int pad=0; pad<2; pad++) {
if (config.disablePad[pad]) continue;
for (int j=0; j<dev->pads[pad].numBindings; j++) {
Binding *b = dev->pads[pad].bindings+j;
int cmd = b->command;
int state = dev->virtualControlState[b->controlIndex];
if (!(turbo & b->turbo)) {
if (cmd > 0x0F && cmd != 0x28) {
ProcessButtonBinding(b, s+pad, state);
}
else if ((state>>15) && !(dev->oldVirtualControlState[b->controlIndex]>>15)) {
if (cmd == 0x0F) {
miceEnabled = !miceEnabled;
UpdateEnabledDevices();
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) continue;
for (int j=0; j<dev->pads[port][slot].numBindings; j++) {
Binding *b = dev->pads[port][slot].bindings+j;
int cmd = b->command;
int state = dev->virtualControlState[b->controlIndex];
if (!(turbo & b->turbo)) {
if (cmd > 0x0F && cmd != 0x28) {
ProcessButtonBinding(b, &s[port][slot], state);
}
else if (cmd == 0x0C) {
lockStateChanged[pad] |= LOCK_BUTTONS;
}
else if (cmd == 0x0E) {
lockStateChanged[pad] |= LOCK_DIRECTION;
}
else if (cmd == 0x0D) {
lockStateChanged[pad] |= LOCK_BOTH;
}
else if (cmd == 0x28) {
if (!pads[pad].modeLock) {
if (pads[pad].mode != MODE_DIGITAL)
pads[pad].mode = MODE_DIGITAL;
else
pads[pad].mode = MODE_ANALOG;
else if ((state>>15) && !(dev->oldVirtualControlState[b->controlIndex]>>15)) {
if (cmd == 0x0F) {
miceEnabled = !miceEnabled;
UpdateEnabledDevices();
}
else if (cmd == 0x0C) {
lockStateChanged[port][slot] |= LOCK_BUTTONS;
}
else if (cmd == 0x0E) {
lockStateChanged[port][slot] |= LOCK_DIRECTION;
}
else if (cmd == 0x0D) {
lockStateChanged[port][slot] |= LOCK_BOTH;
}
else if (cmd == 0x28) {
if (!pads[port][slot].modeLock) {
if (pads[port][slot].mode != MODE_DIGITAL)
pads[port][slot].mode = MODE_DIGITAL;
else
pads[port][slot].mode = MODE_ANALOG;
}
}
}
}
@ -371,101 +394,99 @@ void Update(int pad) {
LeaveCriticalSection(&readInputCriticalSection);
}
for (int currentPad = 0; currentPad<2; currentPad++) {
if (config.guitar[currentPad]) {
if (!config.GH2) {
s[currentPad].sticks[1].vert = -s[currentPad].sticks[1].vert;
}
// GH2 hack.
else if (config.GH2) {
const unsigned int oldIdList[5] = {ID_R2, ID_CIRCLE, ID_TRIANGLE, ID_CROSS, ID_SQUARE};
const unsigned int idList[5] = {ID_L2, ID_L1, ID_R1, ID_R2, ID_CROSS};
int values[5];
int i;
for (i=0; i<5; i++) {
int id = oldIdList[i] - 0x1104;
values[i] = s[currentPad].buttons[id];
s[currentPad].buttons[id] = 0;
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) continue;
if (config.padConfigs[port][slot].type == GuitarPad) {
if (!config.GH2) {
s[port][slot].sticks[1].vert = -s[port][slot].sticks[1].vert;
}
s[currentPad].buttons[ID_TRIANGLE-0x1104] = values[1];
for (i=0; i<5; i++) {
int id = idList[i] - 0x1104;
s[currentPad].buttons[id] = values[i];
}
if (abs(s[currentPad].sticks[0].vert) <= 48) {
for (int i=0; i<5; i++) {
unsigned int id = idList[i] - 0x1104;
if (pads[currentPad].sum.buttons[id] < s[currentPad].buttons[id]) {
s[currentPad].buttons[id] = pads[currentPad].sum.buttons[id];
// GH2 hack.
else if (config.GH2) {
const unsigned int oldIdList[5] = {ID_R2, ID_CIRCLE, ID_TRIANGLE, ID_CROSS, ID_SQUARE};
const unsigned int idList[5] = {ID_L2, ID_L1, ID_R1, ID_R2, ID_CROSS};
int values[5];
int i;
for (i=0; i<5; i++) {
int id = oldIdList[i] - 0x1104;
values[i] = s[port][slot].buttons[id];
s[port][slot].buttons[id] = 0;
}
s[port][slot].buttons[ID_TRIANGLE-0x1104] = values[1];
for (i=0; i<5; i++) {
int id = idList[i] - 0x1104;
s[port][slot].buttons[id] = values[i];
}
if (abs(s[port][slot].sticks[0].vert) <= 48) {
for (int i=0; i<5; i++) {
unsigned int id = idList[i] - 0x1104;
if (pads[port][slot].sum.buttons[id] < s[port][slot].buttons[id]) {
s[port][slot].buttons[id] = pads[port][slot].sum.buttons[id];
}
}
}
}
else if (abs(pads[currentPad].sum.sticks[0].vert) <= 48) {
for (int i=0; i<5; i++) {
unsigned int id = idList[i] - 0x1104;
if (pads[currentPad].sum.buttons[id]) {
s[currentPad].buttons[id] = 0;
else if (abs(pads[port][slot].sum.sticks[0].vert) <= 48) {
for (int i=0; i<5; i++) {
unsigned int id = idList[i] - 0x1104;
if (pads[port][slot].sum.buttons[id]) {
s[port][slot].buttons[id] = 0;
}
}
}
}
}
}
if (pads[currentPad].mode == 0x41) {
s[currentPad].sticks[0].horiz +=
s[currentPad].sticks[1].horiz +
s[currentPad].sticks[2].horiz;
s[currentPad].sticks[0].vert +=
s[currentPad].sticks[1].vert +
s[currentPad].sticks[2].vert;
}
if (pads[port][slot].mode == 0x41) {
s[port][slot].sticks[0].horiz +=
s[port][slot].sticks[1].horiz +
s[port][slot].sticks[2].horiz;
s[port][slot].sticks[0].vert +=
s[port][slot].sticks[1].vert +
s[port][slot].sticks[2].vert;
}
CapSum(&s[currentPad]);
if (lockStateChanged[currentPad]) {
if (lockStateChanged[currentPad] & LOCK_BOTH) {
if (pads[currentPad].lockedState != (LOCK_DIRECTION | LOCK_BUTTONS)) {
// Enable the one that's not enabled.
lockStateChanged[currentPad] ^= pads[currentPad].lockedState^(LOCK_DIRECTION | LOCK_BUTTONS);
CapSum(&s[port][slot]);
if (lockStateChanged[port][slot]) {
if (lockStateChanged[port][slot] & LOCK_BOTH) {
if (pads[port][slot].lockedState != (LOCK_DIRECTION | LOCK_BUTTONS)) {
// Enable the one that's not enabled.
lockStateChanged[port][slot] ^= pads[port][slot].lockedState^(LOCK_DIRECTION | LOCK_BUTTONS);
}
else {
// Disable both
lockStateChanged[port][slot] ^= LOCK_DIRECTION | LOCK_BUTTONS;
}
}
else {
// Disable both
lockStateChanged[currentPad] ^= LOCK_DIRECTION | LOCK_BUTTONS;
if (lockStateChanged[port][slot] & LOCK_DIRECTION) {
if (pads[port][slot].lockedState & LOCK_DIRECTION) {
memset(pads[port][slot].lockedSum.sticks, 0, sizeof(pads[port][slot].lockedSum.sticks));
}
else {
memcpy(pads[port][slot].lockedSum.sticks, s[port][slot].sticks, sizeof(pads[port][slot].lockedSum.sticks));
}
pads[port][slot].lockedState ^= LOCK_DIRECTION;
}
if (lockStateChanged[port][slot] & LOCK_BUTTONS) {
if (pads[port][slot].lockedState & LOCK_BUTTONS) {
memset(pads[port][slot].lockedSum.buttons, 0, sizeof(pads[port][slot].lockedSum.buttons));
}
else {
memcpy(pads[port][slot].lockedSum.buttons, s[port][slot].buttons, sizeof(pads[port][slot].lockedSum.buttons));
}
pads[port][slot].lockedState ^= LOCK_BUTTONS;
}
for (i=0; i<sizeof(pads[port][slot].lockedSum)/4; i++) {
if (((int*)&pads[port][slot].lockedSum)[i]) break;
}
if (i==sizeof(pads[port][slot].lockedSum)/4) {
pads[port][slot].lockedState = 0;
}
}
if (lockStateChanged[currentPad] & LOCK_DIRECTION) {
if (pads[currentPad].lockedState & LOCK_DIRECTION) {
memset(pads[currentPad].lockedSum.sticks, 0, sizeof(pads[currentPad].lockedSum.sticks));
}
else {
memcpy(pads[currentPad].lockedSum.sticks, s[currentPad].sticks, sizeof(pads[currentPad].lockedSum.sticks));
}
pads[currentPad].lockedState ^= LOCK_DIRECTION;
}
if (lockStateChanged[currentPad] & LOCK_BUTTONS) {
if (pads[currentPad].lockedState & LOCK_BUTTONS) {
memset(pads[currentPad].lockedSum.buttons, 0, sizeof(pads[currentPad].lockedSum.buttons));
}
else {
memcpy(pads[currentPad].lockedSum.buttons, s[currentPad].buttons, sizeof(pads[currentPad].lockedSum.buttons));
}
pads[currentPad].lockedState ^= LOCK_BUTTONS;
}
for (i=0; i<sizeof(pads[0].lockedSum)/4; i++) {
if (((int*)&pads[0].lockedSum)[i]) break;
}
if (i==sizeof(pads[0].lockedSum)/4) {
pads[currentPad].lockedState = 0;
}
lockStateChanged[port][slot] = 0;
}
lockStateChanged[currentPad] = 0;
}
pads[0].sum = s[0];
pads[1].sum = s[1];
if (config.disablePad[0]) {
memset(&pads[0].sum, 0, sizeof(pads[0].sum));
}
if (config.disablePad[1]) {
memset(&pads[1].sum, 0, sizeof(pads[1].sum));
for (i=0; i<8; i++) {
pads[i&1][i>>1].sum = s[i&1][i>>1];
}
summed[0] = 1;
summed[1] = 1;
@ -477,10 +498,10 @@ void CALLBACK PADupdate(int pad) {
if (config.GSThreadUpdates) Update(pad);
}
inline void SetVibrate(Pad *pad, int motor, u8 val) {
if (val | pad->vibrateVal[motor]) {
dm->SetEffect(pad - pads, motor, val);
pad->vibrateVal[motor] = val;
inline void SetVibrate(int port, int slot, int motor, u8 val) {
if (val || pads[port][slot].vibrateVal[motor]) {
dm->SetEffect(port,slot, motor, val);
pads[port][slot].vibrateVal[motor] = val;
}
}
@ -527,34 +548,48 @@ char* CALLBACK PS2EgetLibName(void) {
//}
void CALLBACK PADshutdown() {
pads[0].initialized = 0;
pads[1].initialized = 0;
for (int i=0; i<8; i++)
pads[i&1][i>>1].initialized = 0;
UnloadConfigs();
}
inline void StopVibrate() {
for (int i=0; i<4; i++) {
SetVibrate(&pads[i/2], i&1, 0);
for (int i=0; i<8; i++) {
SetVibrate(i&1, i>>1, 0, 0);
SetVibrate(i&1, i>>1, 1, 0);
}
}
inline void ResetVibrate(Pad *pad) {
SetVibrate(pad, 0, 0);
SetVibrate(pad, 1, 0);
((int*)(pad->vibrate))[0] = 0xFFFFFF5A;
((int*)(pad->vibrate))[1] = 0xFFFFFFFF;
inline void ResetVibrate(int port, int slot) {
SetVibrate(port, slot, 0, 0);
SetVibrate(port, slot, 1, 0);
((int*)(pads[port][slot].vibrate))[0] = 0xFFFFFF5A;
((int*)(pads[port][slot].vibrate))[1] = 0xFFFFFFFF;
}
void ResetPad(int pad) {
memset(&pads[pad], 0, sizeof(pads[0]));
pads[pad].mode = MODE_DIGITAL;
pads[pad].umask[0] = pads[pad].umask[1] = 0xFF;
ResetVibrate(pads+pad);
if (config.AutoAnalog[pad]) {
pads[pad].mode = MODE_ANALOG;
void ResetPad(int port, int slot) {
memset(&pads[port][slot], 0, sizeof(pads[0]));
pads[port][slot].mode = MODE_DIGITAL;
pads[port][slot].umask[0] = pads[port][slot].umask[1] = 0xFF;
ResetVibrate(port, slot);
if (config.padConfigs[port][slot].autoAnalog) {
pads[port][slot].mode = MODE_ANALOG;
}
}
struct QueryInfo {
u8 port;
u8 slot;
u8 lastByte;
u8 currentCommand;
u8 numBytes;
u8 queryDone;
u8 response[42];
} query = {0,0,0,0, 0,0xFF, 0xF3};
int saveStateIndex = 0;
s32 CALLBACK PADinit(u32 flags) {
// Note: Won't load settings if already loaded.
if (LoadSettings() < 0) {
@ -572,10 +607,13 @@ s32 CALLBACK PADinit(u32 flags) {
#endif
pad --;
ResetPad(pad);
ResetPad(pad, 0);
pads[pad].initialized = 1;
pads[pad][0].initialized = 1;
memset(slots, 0, sizeof(slots));
query.lastByte = 1;
query.numBytes = 0;
return 0;
}
@ -618,17 +656,6 @@ static const u8 queryMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const u8 setNativeMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A};
struct QueryInfo {
u8 pad;
u8 lastByte;
u8 currentCommand;
u8 numBytes;
u8 queryDone;
u8 response[42];
} query = {0,0,0,0, 0,0xFF, 0xF3};
int saveStateIndex = 0;
// Implements a couple of the hacks, also responsible for monitoring device addition/removal and focus
// changes.
ExtraWndProcResult HackWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
@ -759,15 +786,14 @@ s32 CALLBACK PADopen(void *pDsp) {
}
restoreFullScreen = 0;
}
memset(&pads[0].sum, 0, sizeof(pads[0].sum));
memset(&pads[0].lockedSum, 0, sizeof(pads[0].lockedSum));
pads[0].lockedState = 0;
memset(&pads[1].sum, 0, sizeof(pads[0].sum));
memset(&pads[1].lockedSum, 0, sizeof(pads[0].lockedSum));
pads[1].lockedState = 0;
for (int port=0; port<2; port++) {
for (int slot=0; slot<4; slot++) {
memset(&pads[port][slot].sum, 0, sizeof(pads[port][slot].sum));
memset(&pads[port][slot].lockedSum, 0, sizeof(pads[port][slot].lockedSum));
pads[port][slot].lockedState = 0;
}
}
query.lastByte = 1;
query.numBytes = 0;
// I'd really rather use this line, but GetActiveWindow() does not have complete specs.
// It *seems* to return null when no window from this thread has focus, but the
// Microsoft specs seem to imply it returns the window from this thread that would have focus,
@ -794,7 +820,8 @@ u8 CALLBACK PADstartPoll(int pad) {
pad--;
if ((unsigned int)pad <= 1) {
query.queryDone = 0;
query.pad = pad;
query.port = pad;
query.slot = slots[query.port];
query.numBytes = 2;
query.lastByte = 0;
DEBUG_IN(pad);
@ -835,7 +862,7 @@ u8 CALLBACK PADpoll(u8 value) {
return query.response[++query.lastByte];
}//*/
int i;
Pad *pad = &pads[query.pad];
Pad *pad = &pads[query.port][query.slot];
if (query.lastByte == 0) {
query.lastByte++;
query.currentCommand = value;
@ -853,7 +880,7 @@ u8 CALLBACK PADpoll(u8 value) {
query.response[2] = 0x5A;
{
if (!config.GSThreadUpdates) {
Update(pad != pads);
Update(query.port);
}
ButtonSum *sum = &pad->sum;
@ -864,7 +891,7 @@ u8 CALLBACK PADpoll(u8 value) {
for (i = 0; i<8; i++) {
b2 -= (sum->buttons[i+4]>=128) << i;
}
if (config.guitar[query.pad] && !config.GH2) {
if (config.padConfigs[query.port][query.slot].type == GuitarPad && !config.GH2) {
sum->sticks[0].horiz = -255;
// Not sure about this. Forces wammy to be from 0 to 0x7F.
// if (sum->sticks[2].vert > 0) sum->sticks[2].vert = 0;
@ -936,11 +963,11 @@ u8 CALLBACK PADpoll(u8 value) {
// SET_MODE_AND_LOCK
case 0x44:
SET_RESULT(setMode);
ResetVibrate(pad);
ResetVibrate(query.port, query.slot);
break;
// QUERY_MODEL_AND_MODE
case 0x45:
if (!config.guitar[query.pad] || config.GH2) SET_FINAL_RESULT(queryModelDS2)
if (config.padConfigs[query.port][query.slot].type != GuitarPad || config.GH2) SET_FINAL_RESULT(queryModelDS2)
else SET_FINAL_RESULT(queryModelDS1);
query.response[5] = pad->mode != MODE_DIGITAL;
break;
@ -960,7 +987,7 @@ u8 CALLBACK PADpoll(u8 value) {
case 0x4D:
memcpy(query.response+2, pad->vibrate, 7);
query.numBytes = 9;
ResetVibrate(pad);
ResetVibrate(query.port, query.slot);
break;
// SET_DS2_NATIVE_MODE
case 0x4F:
@ -980,10 +1007,10 @@ u8 CALLBACK PADpoll(u8 value) {
// READ_DATA_AND_VIBRATE
case 0x42:
if (query.lastByte == pad->vibrateI[0]) {
SetVibrate(pad, 1, 255*(0!=value));
SetVibrate(query.port, query.slot, 1, 255*(0!=value));
}
else if (query.lastByte == pad->vibrateI[1]) {
SetVibrate(pad, 0, value);
SetVibrate(query.port, query.slot, 0, value);
}
break;
// CONFIG_MODE
@ -1005,7 +1032,7 @@ u8 CALLBACK PADpoll(u8 value) {
}
else {
pad->modeLock = 0;
if (pad->mode == MODE_DIGITAL && config.AutoAnalog[query.pad]) {
if (pad->mode == MODE_DIGITAL && config.padConfigs[query.port][query.slot].autoAnalog) {
pad->mode = MODE_ANALOG;
}
}
@ -1188,14 +1215,6 @@ keyEvent* CALLBACK PADkeyEvent() {
#define PAD_SAVE_STATE_VERSION 0
struct PadFreezeData {
u8 mode;
u8 locked;
u8 config;
u8 vibrate[8];
u8 umask[2];
};
struct PadPluginFreezeData {
char format[8];
// Currently all different versions are incompatible.
@ -1204,6 +1223,8 @@ struct PadPluginFreezeData {
// So when loading, know which plugin's settings I'm loading.
// Not a big deal. Use a static variable when saving to figure it out.
u8 port;
// active slot for port
u8 slot;
// Currently only use padData[0]. Save room for all 4 slots for simplicity.
PadFreezeData padData[4];
};
@ -1215,37 +1236,40 @@ s32 CALLBACK PADfreeze(int mode, freezeData *data) {
else if (mode == FREEZE_LOAD) {
if (data->size < sizeof(PadPluginFreezeData)) return 0;
PadPluginFreezeData &pdata = *(PadPluginFreezeData*)(data->data);
if (pdata.version != PAD_SAVE_STATE_VERSION || strcmp(pdata.format, "PadMode")) return 0;
if (pdata.version != PAD_SAVE_STATE_VERSION || strcmp(pdata.format, "PadMode")) {
return 0;
}
StopVibrate();
int port = pdata.port;
for (int i=0; i<1; i++) {
u8 mode = pads[port].mode = pdata.padData[i].mode;
for (int slot=0; slot<4; slot++) {
u8 mode = pads[port][slot].mode = pdata.padData[slot].mode;
if (mode != MODE_DIGITAL && mode != MODE_ANALOG && mode != MODE_DS2_NATIVE) {
ResetPad(i);
ResetPad(port, slot);
continue;
}
pads[port].config = pdata.padData[i].config;
pads[port].modeLock = pdata.padData[i].locked;
memcpy(pads[port].umask, pdata.padData[i].umask, sizeof(pads[port].umask));
pads[port][slot].config = pdata.padData[slot].config;
pads[port][slot].modeLock = pdata.padData[slot].modeLock;
memcpy(pads[port][slot].umask, pdata.padData[slot].umask, sizeof(pads[port][slot].umask));
slots[port] = slot;
// Means I only have to have one chunk of code to parse vibrate info.
// Other plugins don't store it exactly, but think it's technically correct
// to do so, though I could be wrong.
PADstartPoll(i+1);
PADstartPoll(port+1);
PADpoll(0x4D);
PADpoll(0x00);
for (int j=0; j<7; j++) {
PADpoll(pdata.padData[i].vibrate[j]);
PADpoll(pdata.padData[slot].vibrate[j]);
}
}
slots[port] = pdata.slot;
}
else if (mode == FREEZE_SAVE) {
if (data->size != sizeof(PadPluginFreezeData)) return 0;
PadPluginFreezeData &pdata = *(PadPluginFreezeData*)(data->data);
static int nextPort = 0;
if (!pads[nextPort].initialized) nextPort ^= 1;
if (!portInitialized[nextPort]) nextPort ^= 1;
int port = nextPort;
if (!pads[nextPort^1].initialized) nextPort = 0;
if (!portInitialized[nextPort^1]) nextPort = 0;
else nextPort ^= 1;
@ -1253,25 +1277,9 @@ s32 CALLBACK PADfreeze(int mode, freezeData *data) {
strcpy(pdata.format, "PadMode");
pdata.version = PAD_SAVE_STATE_VERSION;
pdata.port = port;
for (int i=0; i<1; i++) {
pdata.padData[i].mode = pads[port].mode;
pdata.padData[i].locked = pads[port].modeLock;
memcpy(pdata.padData[i].umask, pads[port].umask, sizeof(pads[port].umask));
memcpy(pdata.padData[i].vibrate, pads[port].vibrate, sizeof(pads[port].vibrate));
// Means I only have to have one chunk of code to parse vibrate info.
// Other plugins don't store it exactly, but think it's technically correct
// to do so, though I could be wrong.
pads[port].config = 1;
PADstartPoll(port+1);
PADpoll(0x4D);
PADpoll(0x00);
for (int j=0; j<7; j++) {
PADpoll(pdata.padData[port].vibrate[j]);
}
pdata.padData[port].config = pads[port].config;
pdata.slot = slots[port];
for (int slot=0; slot<4; slot++) {
pdata.padData[slot] = pads[port][slot];
}
}
else return -1;

View File

@ -89,7 +89,7 @@ BEGIN
PUSHBUTTON "Left",ID_RSTICK_LEFT,324,144,35,15
PUSHBUTTON "Right",ID_RSTICK_RIGHT,364,144,35,15
PUSHBUTTON "Down",ID_RSTICK_DOWN,342,164,35,15
GROUPBOX "",ID_FF,195,6,222,250
GROUPBOX "",ID_FF,195,6,222,248
COMBOBOX IDC_FF_EFFECT,203,20,206,106,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "",IDC_FF_AXIS1,"msctls_trackbar32",WS_TABSTOP,199,40,214,17
CONTROL "Axis 1",IDC_FF_AXIS1_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,205,60,91,10
@ -153,7 +153,7 @@ BEGIN
PUSHBUTTON "Whammy Bar Down",ID_LSTICK_DOWN,219,164,69,15
PUSHBUTTON "Strum Bar Up",ID_DPAD_UP,336,146,58,15
PUSHBUTTON "Strum Bar Down",ID_DPAD_DOWN,336,164,58,15
GROUPBOX "",ID_FF,195,6,222,250
GROUPBOX "",ID_FF,195,6,222,248
COMBOBOX IDC_FF_EFFECT,203,20,206,106,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "",IDC_FF_AXIS1,"msctls_trackbar32",WS_TABSTOP,199,40,214,17
CONTROL "Axis 1",IDC_FF_AXIS1_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,205,60,91,10
@ -220,20 +220,14 @@ BEGIN
CONTROL "Disable",IDC_M_DISABLE,"Button",BS_AUTORADIOBUTTON,224,63,39,10
CONTROL "Start without mouse focus",IDC_MOUSE_UNFOCUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,75,97,10
CONTROL "Always hide cursor",IDC_FORCE_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,87,71,10
GROUPBOX "Advanced",IDC_STATIC,216,103,192,27
GROUPBOX "Advanced",IDC_STATIC,216,105,192,25
CONTROL "Allow binding multiple PS2 controls to one PC control",IDC_MULTIPLE_BINDING,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,115,182,10
GROUPBOX "Pad Options",IDC_STATIC,7,140,410,67
GROUPBOX "Pad 1",IDC_STATIC,16,150,192,49
CONTROL "Disable pad",IDC_DISABLE_PAD1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,162,53,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,116,182,10
GROUPBOX "Pads",IDC_STATIC,7,140,410,67
CONTROL "",IDC_PAD_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | WS_TABSTOP,17,152,183,48,WS_EX_CLIENTEDGE
COMBOBOX IDC_PAD_TYPE,211,153,140,41,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
CONTROL "Use analog mode whenever possible",IDC_ANALOG_START1,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,174,132,10
CONTROL "Guitar",IDC_GUITAR1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,186,35,10
GROUPBOX "Pad 2",IDC_STATIC,216,150,192,49
CONTROL "Disable pad",IDC_DISABLE_PAD2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,162,53,10
CONTROL "Use analog mode whenever possible",IDC_ANALOG_START2,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,174,132,10
CONTROL "Guitar",IDC_GUITAR2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,186,35,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,211,172,132,10
GROUPBOX "Device Diagnostics",IDC_STATIC,7,211,201,99
CONTROL "",IDC_LIST,"SysListView32",LVS_LIST | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_VSCROLL | WS_TABSTOP,15,224,185,61,WS_EX_CLIENTEDGE
PUSHBUTTON "Test Device",ID_TEST,86,289,57,15

View File

@ -27,7 +27,7 @@ __forceinline int ShortToAxis(int v) {
class XInputDevice : public Device {
// Cached last vibration values by pad and motor.
// Need this, as only one value is changed at a time.
int ps2Vibration[2][2];
int ps2Vibration[2][4][2];
// Minor optimization - cache last set vibration values
// When there's no change, no need to do anything.
XINPUT_VIBRATION xInputVibration;
@ -112,15 +112,17 @@ public:
return 1;
}
void SetEffects(unsigned char pad, unsigned char motor, unsigned char force) {
ps2Vibration[pad][motor] = force;
void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) {
ps2Vibration[port][slot][motor] = force;
int newVibration[2] = {0,0};
for (int p=0; p<2; p++) {
for (int i=0; i<pads[p].numFFBindings; i++) {
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
ForceFeedbackBinding *ffb = &pads[p].ffBindings[i];
newVibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][ffb->motor]) / 255);
newVibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][ffb->motor]) / 255);
for (int s=0; s<4; s++) {
for (int i=0; i<pads[p][s].numFFBindings; i++) {
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i];
newVibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
newVibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
}
}
}
newVibration[0] = abs(newVibration[0]);
@ -140,11 +142,11 @@ public:
}
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {
PadBindings pBackup = pads[0];
pads[0].ffBindings = binding;
pads[0].numFFBindings = 1;
SetEffects(0, binding->motor, 255);
pads[0] = pBackup;
PadBindings pBackup = pads[0][0];
pads[0][0].ffBindings = binding;
pads[0][0].numFFBindings = 1;
SetEffects(0, 0, binding->motor, 255);
pads[0][0] = pBackup;
}
void Deactivate() {

View File

@ -17,7 +17,6 @@
#define IDC_KB_WM 1102
#define IDC_KB_RAW 1103
#define IDC_DISABLE_PAD1 1104
#define IDC_DISABLE_PAD2 1105
#define IDC_M_DISABLE 1106
#define IDC_M_DI 1107
#define IDC_M_WM 1108
@ -28,27 +27,22 @@
#define IDC_CLOSE_HACK3 1113
#define IDC_DEBUG_FILE 1114
#define IDC_GUITAR1 1115
#define IDC_GUITAR2 1116
#define IDC_ANALOG_START1 1117
#define IDC_ANALOG_START2 1118
#define IDC_DISABLE_SCREENSAVER 1119
#define IDC_MOUSE_UNFOCUS 1120
#define IDC_MOUSE_UNFOCUS2 1121
#define IDC_AXIS_BUTTONS 1121
#define IDC_BACKGROUND 1122
#define IDC_MULTIPLE_BINDING 1123
#define IDC_DISABLE_SCREENSAVER2 1124
#define IDC_FORCE_HIDE 1124
#define IDC_FORCE_HIDE2 1125
#define IDC_GH2_HACK 1125
#define IDC_FORCEFEEDBACK_HACK1 1126
#define IDC_GH2_HACK2 1126
#define IDC_VISTA_VOLUME 1126
#define IDC_DISABLE_SCREENSAVER4 1127
#define IDC_FORCEFEEDBACK_HACK2 1127
#define IDC_FORCE_HIDE3 1127
#define IDC_GS_THREAD_INPUT 1128
#define IDC_SAVE_STATE_TITLE 1129
#define IDC_PAD_LIST 1133
#define IDC_COMBO1 1134
#define IDC_PAD_TYPE 1134
#define IDC_SLIDER1 0x1000
#define IDC_FLIP1 0x1001
#define IDC_AXIS_DIRECTION 0x1002
@ -148,7 +142,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 112
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1130
#define _APS_NEXT_CONTROL_VALUE 1135
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif