GCPad/Wiimote New (ControllerInterface): Some tweaks to the DirectInput code. (fix for a random gamepad which didn't work)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6159 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Jordan Woyak 2010-09-02 00:03:25 +00:00
parent 9e17007c90
commit 7afd393acb
2 changed files with 111 additions and 69 deletions

View File

@ -10,6 +10,25 @@ namespace ciface
namespace DInput
{
static const struct
{
GUID guid;
const char* name;
} force_type_names[] =
{
{GUID_ConstantForce, "Constant"},
{GUID_RampForce, "Ramp"},
{GUID_Square, "Square"},
{GUID_Sine, "Sine"},
{GUID_Triangle, "Triangle"},
{GUID_SawtoothUp, "SawtoothUp"},
{GUID_SawtoothDown, "SawtoothDown"},
//{GUID_Spring, "Spring"},
//{GUID_Damper, "Damper"},
//{GUID_Inertia, "Inertia"},
//{GUID_Friction, "Friction"},
};
#define DATA_BUFFER_SIZE 32
#ifdef NO_DUPLICATE_DINPUT_XINPUT
@ -182,38 +201,36 @@ Joystick::Joystick( /*const LPCDIDEVICEINSTANCE lpddi, */const LPDIRECTINPUTDEVI
, m_index(index)
//, m_name(TStringToString(lpddi->tszInstanceName))
{
// this needs to be done before GetCapabilities() maybe?
m_device->Acquire();
// get joystick caps
DIDEVCAPS js_caps;
ZeroMemory( &js_caps, sizeof(js_caps) );
js_caps.dwSize = sizeof(js_caps);
m_device->GetCapabilities(&js_caps);
if (FAILED(m_device->GetCapabilities(&js_caps)))
return;
// max of 32 buttons and 4 hats / the limit of the data format i am using
js_caps.dwButtons = std::min((DWORD)32, js_caps.dwButtons);
js_caps.dwPOVs = std::min((DWORD)4, js_caps.dwPOVs);
//m_must_poll = (js_caps.dwFlags & DIDC_POLLEDDATAFORMAT) != 0;
// polled or buffered data
m_must_poll = (js_caps.dwFlags & DIDC_POLLEDDATAFORMAT) != 0;
if (false == m_must_poll)
{
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = DATA_BUFFER_SIZE;
// set the buffer size,
// if we can't set the property, we can't use buffered data,
// must use polling, which apparently doesn't work as well
m_must_poll = (DI_OK != m_device->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph));
}
m_device->Acquire();
// if we can't set the property, we can't use buffered data
m_buffered = SUCCEEDED(m_device->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph));
// buttons
for ( unsigned int i = 0; i < js_caps.dwButtons; ++i )
AddInput( new Button( i ) );
// hats
for ( unsigned int i = 0; i < js_caps.dwPOVs; ++i )
{
@ -221,15 +238,16 @@ Joystick::Joystick( /*const LPCDIDEVICEINSTANCE lpddi, */const LPDIRECTINPUTDEVI
for ( unsigned int d = 0; d<4; ++d )
AddInput( new Hat( i, d ) );
}
// get up to 6 axes and 2 sliders
// screw EnumObjects, just go through all the axis offsets and try to GetProperty
// this should be more foolproof, less code, and probably faster
for (unsigned int offset = 0; offset < DIJOFS_BUTTON(0) / sizeof(LONG); ++offset)
{
DIPROPRANGE range;
range.diph.dwSize = sizeof(range);
range.diph.dwHeaderSize = sizeof(range.diph);
range.diph.dwHow = DIPH_BYOFFSET;
// screw EnumObjects, just go through all the axis offsets and try to GetProperty
// this should be more foolproof, less code, and probably faster
for (unsigned int offset = 0; offset < DIJOFS_BUTTON(0) / sizeof(LONG); ++offset)
{
range.diph.dwObj = offset * sizeof(LONG);
// try to set some nice power of 2 values (8192)
range.lMin = -(1 << 13);
@ -247,6 +265,8 @@ Joystick::Joystick( /*const LPCDIDEVICEINSTANCE lpddi, */const LPDIRECTINPUTDEVI
}
}
// TODO: check for DIDC_FORCEFEEDBACK in devcaps?
// get supported ff effects
std::list<DIDEVICEOBJECTINSTANCE> objects;
m_device->EnumObjects(DIEnumDeviceObjectsCallback, (LPVOID)&objects, DIDFT_AXIS);
@ -256,28 +276,40 @@ Joystick::Joystick( /*const LPCDIDEVICEINSTANCE lpddi, */const LPDIRECTINPUTDEVI
// temporary
DWORD rgdwAxes[] = {DIJOFS_X, DIJOFS_Y};
LONG rglDirection[] = {0, 0};
DICONSTANTFORCE cf = { 0 };
DIEFFECT eff;
ZeroMemory(&eff, sizeof(DIEFFECT));
eff.dwSize = sizeof(DIEFFECT);
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
eff.dwDuration = INFINITE;
eff.dwSamplePeriod = 0;
eff.dwGain = DI_FFNOMINALMAX;
eff.dwTriggerButton = DIEB_NOTRIGGER;
eff.dwTriggerRepeatInterval = 0;
eff.cAxes = std::min((DWORD)2, (DWORD)objects.size());
eff.rgdwAxes = rgdwAxes;
eff.rglDirection = rglDirection;
eff.lpEnvelope = NULL;
eff.dwStartDelay = 0;
// TODO: this only works for Constant force
DICONSTANTFORCE cf = {0};
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
eff.lpvTypeSpecificParams = &cf;
LPDIRECTINPUTEFFECT pEffect;
if (SUCCEEDED(m_device->CreateEffect(GUID_ConstantForce, &eff, &pEffect, NULL)))
for (unsigned int f = 0, i = 0; f < sizeof(force_type_names)/sizeof(*force_type_names); ++f)
{
// temp
AddOutput( new Force( 0 ) );
// TODO: diff specific params for different effect types
//eff.cbTypeSpecificParams = sizeof(DIPERIODIC);
//eff.lpvTypeSpecificParams = &cf;
LPDIRECTINPUTEFFECT pEffect;
if (SUCCEEDED(m_device->CreateEffect(force_type_names[f].guid, &eff, &pEffect, NULL)))
{
AddOutput(new Force(i++, f));
m_state_out.push_back(EffectState(pEffect));
}
}
}
// disable autocentering
if (Outputs().size())
@ -297,7 +329,8 @@ Joystick::Joystick( /*const LPCDIDEVICEINSTANCE lpddi, */const LPDIRECTINPUTDEVI
Joystick::~Joystick()
{
// release the ff effect iface's
std::vector<EffectState>::iterator i = m_state_out.begin(),
std::vector<EffectState>::iterator
i = m_state_out.begin(),
e = m_state_out.end();
for (; i!=e; ++i)
{
@ -338,21 +371,16 @@ bool Joystick::UpdateInput()
{
HRESULT hr = 0;
if (m_must_poll)
{
// just always poll,
// msdn says if this isn't needed it doesnt do anything
m_device->Poll();
hr = m_device->GetDeviceState(sizeof(m_state_in), &m_state_in);
}
else
bool need_ = true;
if (m_buffered)
{
DIDEVICEOBJECTDATA evtbuf[DATA_BUFFER_SIZE];
DWORD numevents;
//DWORD wantevents = INFINITE;
//hr = m_device->GetDeviceData(sizeof(*evtbuf), NULL, &wantevents, DIGDD_PEEK);
GETDEVDATA :
numevents = DATA_BUFFER_SIZE;
DWORD numevents = DATA_BUFFER_SIZE;
hr = m_device->GetDeviceData(sizeof(*evtbuf), evtbuf, &numevents, 0);
if (SUCCEEDED(hr))
@ -367,14 +395,15 @@ GETDEVDATA :
((BYTE*)&m_state_in)[evt->dwOfs] = (BYTE)evt->dwData;
}
// if there is more data to be received
// it seems like to me this could cause problems,
// if the device was producing so many events that GetDeviceData always returned bufferoverflow
// it seems to be working fine tho
// we lost some data, attempt to use GetDeviceState
// maybe this isn't the best thing to do
// maybe I should clear the input state?
if (DI_BUFFEROVERFLOW == hr)
goto GETDEVDATA;
hr = m_device->GetDeviceState(sizeof(m_state_in), &m_state_in);
}
}
else
hr = m_device->GetDeviceState(sizeof(m_state_in), &m_state_in);
// try reacquire if input lost
if (DIERR_INPUTLOST == hr || DIERR_NOTACQUIRED == hr)
@ -394,9 +423,22 @@ bool Joystick::UpdateOutput()
if (i->changed)
{
i->changed = false;
// TODO: this only works for constant force
DICONSTANTFORCE cf;
cf.lMagnitude = LONG(10000 * i->magnitude);
// TODO: different specific params for different effect types
//DIPERIODIC pf;
//pf.dwMagnitude = LONG(10000 * i->magnitude);
//pf.lOffset = 0;
//pf.dwPhase = 0;
//pf.dwPeriod = 0;
//DIRAMPFORCE rf;
//rf.lStart = LONG(10000 * i->magnitude);
//rf.lEnd = 0;
if (cf.lMagnitude)
{
DIEFFECT eff;
@ -455,8 +497,7 @@ std::string Joystick::Hat::GetName() const
std::string Joystick::Force::GetName() const
{
// temporary
return "Constant";
return force_type_names[m_type].name;
}
// get / set state

View File

@ -98,10 +98,11 @@ protected:
public:
std::string GetName() const;
protected:
Force( const unsigned int index ) : m_index(index) {}
Force(const unsigned int index, const unsigned int type) : m_index(index), m_type(type) {}
void SetState( const ControlState state, EffectState* const joystate );
private:
const unsigned int m_index;
const unsigned int m_type;
};
bool UpdateInput();
@ -128,7 +129,7 @@ private:
DIJOYSTATE m_state_in;
std::vector<EffectState> m_state_out;
bool m_must_poll;
bool m_buffered;
};
}