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

View File

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

View File

@ -67,12 +67,14 @@ Device::~Device() {
// Generally called by deactivate, but just in case... // Generally called by deactivate, but just in case...
FreeState(); FreeState();
int i; int i;
for (int pad=0; pad<2; pad++) { for (int port=0; port<2; port++) {
free(pads[pad].bindings); for (int slot=0; slot<4; slot++) {
for (i=0; i<pads[pad].numFFBindings; i++) { free(pads[port][slot].bindings);
free(pads[pad].ffBindings[i].axes); 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); free(virtualControls);
@ -112,11 +114,13 @@ void Device::AddFFAxis(const wchar_t *displayName, int id) {
ffAxes[numFFAxes].id = id; ffAxes[numFFAxes].id = id;
ffAxes[numFFAxes].displayName = wcsdup(displayName); ffAxes[numFFAxes].displayName = wcsdup(displayName);
numFFAxes++; numFFAxes++;
for (int pad=0; pad<2; pad++) { for (int port=0; port<2; port++) {
for (int i=0; i<pads[pad].numFFBindings; i++) { for (int slot=0; slot<4; slot++) {
ForceFeedbackBinding *b = pads[pad].ffBindings+i; for (int i=0; i<pads[port][slot].numFFBindings; i++) {
b->axes = (AxisEffectInfo*) realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes)); ForceFeedbackBinding *b = pads[port][slot].ffBindings+i;
memset(b->axes + (numFFAxes-1), 0, sizeof(AxisEffectInfo)); 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; return control;
} }
void Device::SetEffects(unsigned char pad, unsigned char motor, unsigned char force) { void Device::SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) {
for (int i=0; i<pads[pad].numFFBindings; i++) { for (int i=0; i<pads[port][slot].numFFBindings; i++) {
ForceFeedbackBinding *binding = pads[pad].ffBindings+i; ForceFeedbackBinding *binding = pads[port][slot].ffBindings+i;
if (binding->motor == motor) { if (binding->motor == motor) {
SetEffect(binding, force); SetEffect(binding, force);
} }
@ -451,7 +455,7 @@ ForceFeedbackAxis *Device::GetForceFeedbackAxis(int id) {
void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) { void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
int *oldMatches = (int*) malloc(sizeof(int) * numOldDevices); int *oldMatches = (int*) malloc(sizeof(int) * numOldDevices);
int *matches = (int*) malloc(sizeof(int) * numDevices); int *matches = (int*) malloc(sizeof(int) * numDevices);
int i, j, pad; int i, j, port, slot;
Device *old, *dev; Device *old, *dev;
for (i=0; i<numDevices; i++) { for (i=0; i<numDevices; i++) {
matches[i] = -1; matches[i] = -1;
@ -459,10 +463,12 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
for (i=0; i<numOldDevices; i++) { for (i=0; i<numOldDevices; i++) {
oldMatches[i] = -2; oldMatches[i] = -2;
old = oldDevices[i]; old = oldDevices[i];
for (pad=0; pad<2; pad++) { for (port=0; port<2; port++) {
if (old->pads[pad].numBindings + old->pads[pad].numFFBindings) { for (slot=0; slot<4; slot++) {
// Means that there are bindings. if (old->pads[port][slot].numBindings + old->pads[port][slot].numFFBindings) {
oldMatches[i] = -1; // Means that there are bindings.
oldMatches[i] = -1;
}
} }
} }
} }
@ -514,37 +520,39 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) {
} }
else { else {
dev = devices[oldMatches[i]]; dev = devices[oldMatches[i]];
for (pad=0; pad<2; pad++) { for (port=0; port<2; port++) {
if (old->pads[pad].numBindings) { for (slot=0; slot<4; slot++) {
dev->pads[pad].bindings = (Binding*) malloc(old->pads[pad].numBindings * sizeof(Binding)); if (old->pads[port][slot].numBindings) {
for (int j=0; j<old->pads[pad].numBindings; j++) { dev->pads[port][slot].bindings = (Binding*) malloc(old->pads[port][slot].numBindings * sizeof(Binding));
Binding *bo = old->pads[pad].bindings + j; for (int j=0; j<old->pads[port][slot].numBindings; j++) {
Binding *bn = dev->pads[pad].bindings + dev->pads[pad].numBindings; Binding *bo = old->pads[port][slot].bindings + j;
VirtualControl *cn = dev->GetVirtualControl(old->virtualControls[bo->controlIndex].uid); Binding *bn = dev->pads[port][slot].bindings + dev->pads[port][slot].numBindings;
if (cn) { VirtualControl *cn = dev->GetVirtualControl(old->virtualControls[bo->controlIndex].uid);
*bn = *bo; if (cn) {
bn->controlIndex = cn - dev->virtualControls; *bn = *bo;
dev->pads[pad].numBindings++; bn->controlIndex = cn - dev->virtualControls;
dev->pads[port][slot].numBindings++;
}
} }
} }
} if (old->pads[port][slot].numFFBindings) {
if (old->pads[pad].numFFBindings) { dev->pads[port][slot].ffBindings = (ForceFeedbackBinding*) malloc(old->pads[port][slot].numFFBindings * sizeof(ForceFeedbackBinding));
dev->pads[pad].ffBindings = (ForceFeedbackBinding*) malloc(old->pads[pad].numFFBindings * sizeof(ForceFeedbackBinding)); for (int j=0; j<old->pads[port][slot].numFFBindings; j++) {
for (int j=0; j<old->pads[pad].numFFBindings; j++) { ForceFeedbackBinding *bo = old->pads[port][slot].ffBindings + j;
ForceFeedbackBinding *bo = old->pads[pad].ffBindings + j; ForceFeedbackBinding *bn = dev->pads[port][slot].ffBindings + dev->pads[port][slot].numFFBindings;
ForceFeedbackBinding *bn = dev->pads[pad].ffBindings + dev->pads[pad].numFFBindings; ForceFeedbackEffectType *en = dev->GetForcefeedbackEffect(old->ffEffectTypes[bo->effectIndex].effectID);
ForceFeedbackEffectType *en = dev->GetForcefeedbackEffect(old->ffEffectTypes[bo->effectIndex].effectID); if (en) {
if (en) { *bn = *bo;
*bn = *bo; bn->effectIndex = en - dev->ffEffectTypes;
bn->effectIndex = en - dev->ffEffectTypes; bn->axes = (AxisEffectInfo*)calloc(dev->numFFAxes, sizeof(AxisEffectInfo));
bn->axes = (AxisEffectInfo*)calloc(dev->numFFAxes, sizeof(AxisEffectInfo)); for (int k=0; k<old->numFFAxes; k++) {
for (int k=0; k<old->numFFAxes; k++) { ForceFeedbackAxis *newAxis = dev->GetForceFeedbackAxis(old->ffAxes[k].id);
ForceFeedbackAxis *newAxis = dev->GetForceFeedbackAxis(old->ffAxes[k].id); if (newAxis) {
if (newAxis) { bn->axes[newAxis - dev->ffAxes] = bo->axes[k];
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); 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++) { for (int i=0; i<numDevices; i++) {
Device *dev = devices[i]; Device *dev = devices[i];
if (dev->enabled && dev->numFFEffectTypes) { 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 // Virtual controls. All basically act like pressure sensitivity buttons, with
// values between 0 and 2^16. 2^16 is fully down, 0 is up. Larger values // values between 0 and 2^16. 2^16 is fully down, 0 is up. Larger values
@ -267,7 +267,7 @@ public:
// Note: Only used externally for binding, so if override the other one, can assume // Note: Only used externally for binding, so if override the other one, can assume
// all other forces are currently 0. // all other forces are currently 0.
inline virtual void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {} inline virtual void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {}
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(). // Called after reading. Basically calls FlipState().
// Some device types (Those that don't incrementally update) // Some device types (Those that don't incrementally update)
@ -303,7 +303,7 @@ public:
// Called after reading state, after Update(). // Called after reading state, after Update().
void PostRead(); 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. // Update does this as needed.
// void GetInput(void *v); // 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) { if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) {
KBDLLHOOKSTRUCT* key = (KBDLLHOOKSTRUCT*) lParam; KBDLLHOOKSTRUCT* key = (KBDLLHOOKSTRUCT*) lParam;
if (key->vkCode < 256) { if (key->vkCode < 256) {
for (int i=0; i<ikhd->pads[0].numBindings; i++) { for (int i=0; i<ikhd->pads[0][0].numBindings; i++) {
if (ikhd->pads[0].bindings[i].controlIndex == key->vkCode) { if (ikhd->pads[0][0].bindings[i].controlIndex == key->vkCode) {
return 1; return 1;
} }
} }

View File

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

View File

@ -89,7 +89,7 @@ BEGIN
PUSHBUTTON "Left",ID_RSTICK_LEFT,324,144,35,15 PUSHBUTTON "Left",ID_RSTICK_LEFT,324,144,35,15
PUSHBUTTON "Right",ID_RSTICK_RIGHT,364,144,35,15 PUSHBUTTON "Right",ID_RSTICK_RIGHT,364,144,35,15
PUSHBUTTON "Down",ID_RSTICK_DOWN,342,164,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 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 "",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 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 "Whammy Bar Down",ID_LSTICK_DOWN,219,164,69,15
PUSHBUTTON "Strum Bar Up",ID_DPAD_UP,336,146,58,15 PUSHBUTTON "Strum Bar Up",ID_DPAD_UP,336,146,58,15
PUSHBUTTON "Strum Bar Down",ID_DPAD_DOWN,336,164,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 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 "",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 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 "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 "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 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, CONTROL "Allow binding multiple PS2 controls to one PC control",IDC_MULTIPLE_BINDING,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,115,182,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,116,182,10
GROUPBOX "Pad Options",IDC_STATIC,7,140,410,67 GROUPBOX "Pads",IDC_STATIC,7,140,410,67
GROUPBOX "Pad 1",IDC_STATIC,16,150,192,49 CONTROL "",IDC_PAD_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | WS_TABSTOP,17,152,183,48,WS_EX_CLIENTEDGE
CONTROL "Disable pad",IDC_DISABLE_PAD1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,162,53,10 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, CONTROL "Use analog mode whenever possible",IDC_ANALOG_START1,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,174,132,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,211,172,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
GROUPBOX "Device Diagnostics",IDC_STATIC,7,211,201,99 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 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 PUSHBUTTON "Test Device",ID_TEST,86,289,57,15

View File

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

View File

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