Skip to content

Commit

Permalink
Merge pull request #12 from Armada651/osx_rumble
Browse files Browse the repository at this point in the history
OS X Rumble Support
  • Loading branch information
delroth committed Feb 9, 2014
2 parents 56603b2 + 2063edd commit 9da6900
Show file tree
Hide file tree
Showing 13 changed files with 719 additions and 253 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Expand Up @@ -242,6 +242,7 @@ if(APPLE)
find_library(IOK_LIBRARY IOKit)
find_library(QUICKTIME_LIBRARY QuickTime)
find_library(WEBKIT_LIBRARY WebKit)
find_library(FORCEFEEDBACK ForceFeedback)
endif()

if(WIN32)
Expand Down
1 change: 1 addition & 0 deletions Source/Core/DolphinWX/CMakeLists.txt
Expand Up @@ -141,6 +141,7 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
${CORESERV_LIBRARY}
${IOB_LIBRARY}
${IOK_LIBRARY}
${FORCEFEEDBACK}
)
if(wxWidgets_FOUND)
list(APPEND LIBS
Expand Down
6 changes: 4 additions & 2 deletions Source/Core/InputCommon/CMakeLists.txt
Expand Up @@ -12,13 +12,15 @@ if(WIN32)
ControllerInterface/DInput/DInputJoystick.cpp
ControllerInterface/DInput/DInputKeyboardMouse.cpp
ControllerInterface/SDL/SDL.cpp
ControllerInterface/XInput/XInput.cpp)
ControllerInterface/XInput/XInput.cpp
ControllerInterface/ForceFeedback/ForceFeedbackDevice.cpp)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(SRCS ${SRCS}
ControllerInterface/OSX/OSX.mm
ControllerInterface/OSX/OSXKeyboard.mm
ControllerInterface/OSX/OSXJoystick.mm
ControllerInterface/SDL/SDL.cpp)
ControllerInterface/SDL/SDL.cpp
ControllerInterface/ForceFeedback/ForceFeedbackDevice.cpp)
elseif(X11_FOUND)
set(SRCS ${SRCS}
ControllerInterface/SDL/SDL.cpp
Expand Down
209 changes: 3 additions & 206 deletions Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.cpp
Expand Up @@ -14,30 +14,6 @@ namespace ciface
namespace DInput
{

// template instantiation
template class Joystick::Force<DICONSTANTFORCE>;
template class Joystick::Force<DIRAMPFORCE>;
template class Joystick::Force<DIPERIODIC>;

static const struct
{
GUID guid;
const char* name;
} force_type_names[] =
{
{GUID_ConstantForce, "Constant"}, // DICONSTANTFORCE
{GUID_RampForce, "Ramp"}, // DIRAMPFORCE
{GUID_Square, "Square"}, // DIPERIODIC ...
{GUID_Sine, "Sine"},
{GUID_Triangle, "Triangle"},
{GUID_SawtoothUp, "Sawtooth Up"},
{GUID_SawtoothDown, "Sawtooth Down"},
//{GUID_Spring, "Spring"}, // DICUSTOMFORCE ... < I think
//{GUID_Damper, "Damper"},
//{GUID_Inertia, "Inertia"},
//{GUID_Friction, "Friction"},
};

#define DATA_BUFFER_SIZE 32

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -267,102 +243,18 @@ Joystick::Joystick( /*const LPCDIDEVICEINSTANCE lpddi, */const LPDIRECTINPUTDEVI
}
}

// TODO: check for DIDC_FORCEFEEDBACK in devcaps?

// get supported ff effects
// force feedback
std::list<DIDEVICEOBJECTINSTANCE> objects;
m_device->EnumObjects(DIEnumDeviceObjectsCallback, (LPVOID)&objects, DIDFT_AXIS);
// got some ff axes or something
if ( objects.size() )
{
// temporary
DWORD rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y};
LONG rglDirection[2] = {-200, 0};

DIEFFECT eff;
ZeroMemory(&eff, sizeof(eff));
eff.dwSize = sizeof(DIEFFECT);
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
eff.dwDuration = INFINITE; // (4 * DI_SECONDS)
eff.dwSamplePeriod = 0;
eff.dwGain = DI_FFNOMINALMAX;
eff.dwTriggerButton = DIEB_NOTRIGGER;
eff.dwTriggerRepeatInterval = 0;
eff.cAxes = std::min((DWORD)1, (DWORD)objects.size());
eff.rgdwAxes = rgdwAxes;
eff.rglDirection = rglDirection;

// DIPERIODIC is the largest, so we'll use that
DIPERIODIC f;
eff.lpvTypeSpecificParams = &f;
ZeroMemory(&f, sizeof(f));

// doesn't seem needed
//DIENVELOPE env;
//eff.lpEnvelope = &env;
//ZeroMemory(&env, sizeof(env));
//env.dwSize = sizeof(env);

for (unsigned int f = 0; f < sizeof(force_type_names)/sizeof(*force_type_names); ++f)
{
// ugly if ladder
if (0 == f)
{
DICONSTANTFORCE diCF = {-10000};
diCF.lMagnitude = DI_FFNOMINALMAX;
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
eff.lpvTypeSpecificParams = &diCF;
}
else if (1 == f)
{
eff.cbTypeSpecificParams = sizeof(DIRAMPFORCE);
}
else
{
eff.cbTypeSpecificParams = sizeof(DIPERIODIC);
}

LPDIRECTINPUTEFFECT pEffect;
if (SUCCEEDED(m_device->CreateEffect(force_type_names[f].guid, &eff, &pEffect, NULL)))
{
m_state_out.push_back(EffectState(pEffect));

// ugly if ladder again :/
if (0 == f)
AddOutput(new ForceConstant(f, m_state_out.back()));
else if (1 == f)
AddOutput(new ForceRamp(f, m_state_out.back()));
else
AddOutput(new ForcePeriodic(f, m_state_out.back()));
}
}
}

// disable autocentering
if (Outputs().size())
if (SUCCEEDED(m_device->EnumObjects(DIEnumDeviceObjectsCallback, (LPVOID)&objects, DIDFT_AXIS)))
{
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof( DIPROPDWORD );
dipdw.diph.dwHeaderSize = sizeof( DIPROPHEADER );
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = DIPROPAUTOCENTER_OFF;
m_device->SetProperty( DIPROP_AUTOCENTER, &dipdw.diph );
InitForceFeedback(m_device, objects.size());
}

ClearInputState();
}

Joystick::~Joystick()
{
// release the ff effect iface's
for (EffectState& state : m_state_out)
{
state.iface->Stop();
state.iface->Unload();
state.iface->Release();
}

m_device->Unacquire();
m_device->Release();
}
Expand Down Expand Up @@ -434,42 +326,6 @@ bool Joystick::UpdateInput()
return SUCCEEDED(hr);
}

bool Joystick::UpdateOutput()
{
size_t ok_count = 0;

DIEFFECT eff;
ZeroMemory(&eff, sizeof(eff));
eff.dwSize = sizeof(DIEFFECT);
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;

for (EffectState& state : m_state_out)
{
if (state.params)
{
if (state.size)
{
eff.cbTypeSpecificParams = state.size;
eff.lpvTypeSpecificParams = state.params;
// set params and start effect
ok_count += SUCCEEDED(state.iface->SetParameters(&eff, DIEP_TYPESPECIFICPARAMS | DIEP_START));
}
else
{
ok_count += SUCCEEDED(state.iface->Stop());
}

state.params = NULL;
}
else
{
++ok_count;
}
}

return (m_state_out.size() == ok_count);
}

// get name

std::string Joystick::Button::GetName() const
Expand Down Expand Up @@ -507,12 +363,6 @@ std::string Joystick::Hat::GetName() const
return tmpstr;
}

template <typename P>
std::string Joystick::Force<P>::GetName() const
{
return force_type_names[m_index].name;
}

// get / set state

ControlState Joystick::Axis::GetState() const
Expand All @@ -535,58 +385,5 @@ ControlState Joystick::Hat::GetState() const
return (abs((int)(m_hat / 4500 - m_direction * 2 + 8) % 8 - 4) > 2);
}

void Joystick::ForceConstant::SetState(const ControlState state)
{
const LONG new_val = LONG(10000 * state);

LONG &val = params.lMagnitude;
if (val != new_val)
{
val = new_val;
m_state.params = &params; // tells UpdateOutput the state has changed

// tells UpdateOutput to either start or stop the force
m_state.size = new_val ? sizeof(params) : 0;
}
}

void Joystick::ForceRamp::SetState(const ControlState state)
{
const LONG new_val = LONG(10000 * state);

if (params.lStart != new_val)
{
params.lStart = params.lEnd = new_val;
m_state.params = &params; // tells UpdateOutput the state has changed

// tells UpdateOutput to either start or stop the force
m_state.size = new_val ? sizeof(params) : 0;
}
}

void Joystick::ForcePeriodic::SetState(const ControlState state)
{
const LONG new_val = LONG(10000 * state);

DWORD &val = params.dwMagnitude;
if (val != new_val)
{
val = new_val;
//params.dwPeriod = 0;//DWORD(0.05 * DI_SECONDS); // zero is working fine for me

m_state.params = &params; // tells UpdateOutput the state has changed

// tells UpdateOutput to either start or stop the force
m_state.size = new_val ? sizeof(params) : 0;
}
}

template <typename P>
Joystick::Force<P>::Force(u8 index, EffectState& state)
: m_index(index), m_state(state)
{
ZeroMemory(&params, sizeof(params));
}

}
}
Expand Up @@ -2,14 +2,7 @@
#define _CIFACE_DINPUT_JOYSTICK_H_

#include "../Device.h"

#define DIRECTINPUT_VERSION 0x0800
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <dinput.h>

#include <list>
#include "../ForceFeedback/ForceFeedbackDevice.h"

namespace ciface
{
Expand All @@ -18,18 +11,9 @@ namespace DInput

void InitJoystick(IDirectInput8* const idi8, std::vector<Core::Device*>& devices, HWND hwnd);

class Joystick : public Core::Device
class Joystick : public ForceFeedback::ForceFeedbackDevice
{
private:
struct EffectState
{
EffectState(LPDIRECTINPUTEFFECT eff) : iface(eff), params(NULL), size(0) {}

LPDIRECTINPUTEFFECT iface;
void* params; // null when force hasn't changed
u8 size; // zero when force should stop
};

class Button : public Input
{
public:
Expand Down Expand Up @@ -64,25 +48,8 @@ class Joystick : public Core::Device
const u8 m_index, m_direction;
};

template <typename P>
class Force : public Output
{
public:
std::string GetName() const;
Force(u8 index, EffectState& state);
void SetState(ControlState state);
private:
EffectState& m_state;
P params;
const u8 m_index;
};
typedef Force<DICONSTANTFORCE> ForceConstant;
typedef Force<DIRAMPFORCE> ForceRamp;
typedef Force<DIPERIODIC> ForcePeriodic;

public:
bool UpdateInput();
bool UpdateOutput();

void ClearInputState();

Expand All @@ -98,7 +65,6 @@ class Joystick : public Core::Device
const unsigned int m_index;

DIJOYSTATE m_state_in;
std::list<EffectState> m_state_out;

bool m_buffered;
};
Expand Down

0 comments on commit 9da6900

Please sign in to comment.