Updated rumble for nJoy, fixed a few glitches with half press button and deadzones too.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2840 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
sl1nk3.s 2009-04-02 21:13:58 +00:00
parent e24e2db1a1
commit b0852c1bef
10 changed files with 365 additions and 334 deletions

View File

@ -92,6 +92,7 @@ struct CONTROLLER_MAPPING // GC PAD MAPPING
int triggertype; // Triggers range int triggertype; // Triggers range
std::string SDiagonal; std::string SDiagonal;
bool bSquareToCircle; bool bSquareToCircle;
bool rumble;
int eventnum; // Linux Event Number, Can't be found dynamically yet int eventnum; // Linux Event Number, Can't be found dynamically yet
}; };

View File

@ -271,12 +271,14 @@ void DInput_Read(int _numPAD, SPADStatus* _pPADStatus)
if (dinput.diks[pad[_numPAD].keyForControl[CTL_L]] & 0xFF) if (dinput.diks[pad[_numPAD].keyForControl[CTL_L]] & 0xFF)
{ {
if (triggervalue > 230)
_pPADStatus->button |= PAD_TRIGGER_L; _pPADStatus->button |= PAD_TRIGGER_L;
_pPADStatus->triggerLeft = triggervalue; _pPADStatus->triggerLeft = triggervalue;
} }
if (dinput.diks[pad[_numPAD].keyForControl[CTL_R]] & 0xFF) if (dinput.diks[pad[_numPAD].keyForControl[CTL_R]] & 0xFF)
{ {
if (triggervalue > 230)
_pPADStatus->button |= PAD_TRIGGER_R; _pPADStatus->button |= PAD_TRIGGER_R;
_pPADStatus->triggerRight = triggervalue; _pPADStatus->triggerRight = triggervalue;
} }

View File

@ -111,6 +111,7 @@ void Config::Save(int Slot)
file.Set("General", "SaveByID", g_Config.bSaveByID); file.Set("General", "SaveByID", g_Config.bSaveByID);
file.Set("General", "CheckForFocus", g_Config.bCheckFocus); file.Set("General", "CheckForFocus", g_Config.bCheckFocus);
file.Set("General", "NoTriggerFilter", g_Config.bNoTriggerFilter); file.Set("General", "NoTriggerFilter", g_Config.bNoTriggerFilter);
file.Set("General", "RumbleStrength", g_Config.RumbleStrength);
#ifdef RERECORDING #ifdef RERECORDING
file.Set("General", "Recording", g_Config.bRecording); file.Set("General", "Recording", g_Config.bRecording);
file.Set("General", "Playback", g_Config.bPlayback); file.Set("General", "Playback", g_Config.bPlayback);
@ -171,6 +172,7 @@ void Config::Save(int Slot)
file.Set(SectionName.c_str(), "controllertype", PadMapping[i].controllertype); file.Set(SectionName.c_str(), "controllertype", PadMapping[i].controllertype);
file.Set(SectionName.c_str(), "TriggerType", PadMapping[i].triggertype); file.Set(SectionName.c_str(), "TriggerType", PadMapping[i].triggertype);
file.Set(SectionName.c_str(), "eventnum", PadMapping[i].eventnum); file.Set(SectionName.c_str(), "eventnum", PadMapping[i].eventnum);
file.Set(SectionName.c_str(), "use_rumble", PadMapping[i].rumble);
file.Set(SectionName.c_str(), "Diagonal", PadMapping[i].SDiagonal); file.Set(SectionName.c_str(), "Diagonal", PadMapping[i].SDiagonal);
file.Set(SectionName.c_str(), "SquareToCircle", PadMapping[i].bSquareToCircle); file.Set(SectionName.c_str(), "SquareToCircle", PadMapping[i].bSquareToCircle);
@ -203,6 +205,7 @@ void Config::Load(bool ChangePad, bool ChangeSaveByID)
file.Get("General", "ShowAdvanced", &g_Config.bShowAdvanced, false); file.Get("General", "ShowAdvanced", &g_Config.bShowAdvanced, false);
file.Get("General", "CheckForFocus", &g_Config.bCheckFocus, false); file.Get("General", "CheckForFocus", &g_Config.bCheckFocus, false);
file.Get("General", "NoTriggerFilter", &g_Config.bNoTriggerFilter, false); file.Get("General", "NoTriggerFilter", &g_Config.bNoTriggerFilter, false);
file.Get("General", "RumbleStrength", &g_Config.RumbleStrength, 8);
#ifdef RERECORDING #ifdef RERECORDING
file.Get("General", "Recording", &g_Config.bRecording, false); file.Get("General", "Recording", &g_Config.bRecording, false);
file.Get("General", "Playback", &g_Config.bPlayback, false); file.Get("General", "Playback", &g_Config.bPlayback, false);
@ -263,6 +266,7 @@ void Config::Load(bool ChangePad, bool ChangeSaveByID)
file.Get(SectionName.c_str(), "controllertype", &PadMapping[i].controllertype, 0); file.Get(SectionName.c_str(), "controllertype", &PadMapping[i].controllertype, 0);
file.Get(SectionName.c_str(), "TriggerType", &PadMapping[i].triggertype, 0); file.Get(SectionName.c_str(), "TriggerType", &PadMapping[i].triggertype, 0);
file.Get(SectionName.c_str(), "eventnum", &PadMapping[i].eventnum, 0); file.Get(SectionName.c_str(), "eventnum", &PadMapping[i].eventnum, 0);
file.Get(SectionName.c_str(), "use_rumble", &PadMapping[i].rumble, false);
file.Get(SectionName.c_str(), "Diagonal", &PadMapping[i].SDiagonal, "100%"); file.Get(SectionName.c_str(), "Diagonal", &PadMapping[i].SDiagonal, "100%");
file.Get(SectionName.c_str(), "SquareToCircle", &Tmp, false); PadMapping[i].bSquareToCircle = Tmp; file.Get(SectionName.c_str(), "SquareToCircle", &Tmp, false); PadMapping[i].bSquareToCircle = Tmp;

View File

@ -30,6 +30,7 @@ struct Config
bool bSaveByID; bool bSaveByID;
bool bCheckFocus; bool bCheckFocus;
bool bNoTriggerFilter; bool bNoTriggerFilter;
int RumbleStrength;
#ifdef RERECORDING #ifdef RERECORDING
bool bRecording; bool bRecording;
bool bPlayback; bool bPlayback;

View File

@ -6,7 +6,7 @@
// //
// Author: Falcon4ever (nJoy@falcon4ever.com) // Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net // Site: www.multigesture.net
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// //
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// //
@ -80,6 +80,10 @@ BEGIN_EVENT_TABLE(ConfigBox,wxDialog)
EVT_COMBOBOX(IDC_TRIGGERTYPE, ConfigBox::ChangeSettings) EVT_COMBOBOX(IDC_TRIGGERTYPE, ConfigBox::ChangeSettings)
EVT_COMBOBOX(IDC_DEADZONE, ConfigBox::ChangeSettings) EVT_COMBOBOX(IDC_DEADZONE, ConfigBox::ChangeSettings)
// Rumble settings
EVT_CHECKBOX(IDC_ENABLERUMBLE, ConfigBox::ChangeSettings)
EVT_COMBOBOX(IDC_RUMBLESTRENGTH, ConfigBox::ChangeSettings)
// Advanced settings // Advanced settings
EVT_COMBOBOX(IDCB_MAINSTICK_DIAGONAL, ConfigBox::ChangeSettings) EVT_COMBOBOX(IDCB_MAINSTICK_DIAGONAL, ConfigBox::ChangeSettings)
EVT_CHECKBOX(IDCB_MAINSTICK_S_TO_C, ConfigBox::ChangeSettings) EVT_CHECKBOX(IDCB_MAINSTICK_S_TO_C, ConfigBox::ChangeSettings)
@ -203,7 +207,6 @@ void ConfigBox::OKClick(wxCommandEvent& event)
if (event.GetId() == ID_OK) if (event.GetId() == ID_OK)
{ {
DoSave(); // Save settings DoSave(); // Save settings
//g_Config.Load(); // Reload settings to PadMapping
if(Debugging) PanicAlert("Done"); if(Debugging) PanicAlert("Done");
Close(); // Call OnClose() Close(); // Call OnClose()
} }
@ -217,7 +220,6 @@ void ConfigBox::CancelClick(wxCommandEvent& event)
{ {
// Forget all potential changes to PadMapping by loading the last saved settings // Forget all potential changes to PadMapping by loading the last saved settings
g_Config.Load(); g_Config.Load();
Close(); // Call OnClose() Close(); // Call OnClose()
} }
} }
@ -485,7 +487,13 @@ void ConfigBox::ChangeSettings( wxCommandEvent& event )
UpdateGUI(notebookpage); UpdateGUI(notebookpage);
} }
break; break;
case IDC_ENABLERUMBLE:
PadMapping[notebookpage].rumble = m_Rumble[notebookpage]->IsChecked();
UpdateGUI(notebookpage);
break;
case IDC_RUMBLESTRENGTH:
g_Config.RumbleStrength = m_RStrength[notebookpage]->GetSelection();
break;
case IDC_JOYNAME: case IDC_JOYNAME:
DoChangeJoystick(); DoChangeJoystick();
break; break;
@ -555,17 +563,17 @@ void ConfigBox::UpdateGUI(int _notebookpage)
m_CBShowAdvanced[_notebookpage]->SetValue(g_Config.bShowAdvanced); m_CBShowAdvanced[_notebookpage]->SetValue(g_Config.bShowAdvanced);
m_CBCheckFocus[_notebookpage]->SetValue(g_Config.bCheckFocus); m_CBCheckFocus[_notebookpage]->SetValue(g_Config.bCheckFocus);
m_AdvancedMapFilter[_notebookpage]->SetValue(g_Config.bNoTriggerFilter); m_AdvancedMapFilter[_notebookpage]->SetValue(g_Config.bNoTriggerFilter);
m_RStrength[_notebookpage]->SetSelection(g_Config.RumbleStrength);
#ifdef RERECORDING #ifdef RERECORDING
m_CheckRecording[_notebookpage]->SetValue(g_Config.bRecording); m_CheckRecording[_notebookpage]->SetValue(g_Config.bRecording);
m_CheckPlayback[_notebookpage]->SetValue(g_Config.bPlayback); m_CheckPlayback[_notebookpage]->SetValue(g_Config.bPlayback);
#endif #endif
//LogMsg("Update: %i\n", g_Config.bSaveByID);
// Disabled pages
bool Enabled = PadMapping[_notebookpage].enabled == 1 ? true : false;
// There is no FindItem in linux so this doesn't work // There is no FindItem in linux so this doesn't work
#ifdef _WIN32 #ifdef _WIN32
// Disabled pages
bool Enabled = PadMapping[_notebookpage].enabled == 1 ? true : false;
// Enable or disable all buttons // Enable or disable all buttons
for(int i = IDB_ANALOG_MAIN_X; i <= IDB_BUTTONHALFPRESS; i++) for(int i = IDB_ANALOG_MAIN_X; i <= IDB_BUTTONHALFPRESS; i++)
m_Controller[_notebookpage]->FindItem(i)->Enable(Enabled); m_Controller[_notebookpage]->FindItem(i)->Enable(Enabled);
@ -682,9 +690,18 @@ void ConfigBox::CreateGUIControls()
wxAS_TriggerType.Add(wxString::FromAscii(TriggerType[InputCommon::CTL_TRIGGER_XINPUT])); wxAS_TriggerType.Add(wxString::FromAscii(TriggerType[InputCommon::CTL_TRIGGER_XINPUT]));
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Populate the deadzone list // Populate the deadzone list and the Rumble Strength
// ----------------------------- // -----------------------------
char buffer [8];
char buffer[8];
wxArrayString wxAS_RumbleStrength;
for (int i = 1; i < 11; i++)
{
sprintf (buffer, "%d %%", i*10);
wxAS_RumbleStrength.Add(wxString::FromAscii(buffer));
}
wxArrayString arrayStringFor_Deadzone; wxArrayString arrayStringFor_Deadzone;
for(int x = 1; x <= 100; x++) for(int x = 1; x <= 100; x++)
{ {
@ -692,7 +709,6 @@ void ConfigBox::CreateGUIControls()
arrayStringFor_Deadzone.Add(wxString::FromAscii(buffer)); arrayStringFor_Deadzone.Add(wxString::FromAscii(buffer));
} }
// Populate all four pages // Populate all four pages
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++)
{ {
@ -880,6 +896,17 @@ void ConfigBox::CreateGUIControls()
m_gGenSettingsID[i]->Add(m_CBSaveByID[i], 0, wxEXPAND | wxALL, 3); m_gGenSettingsID[i]->Add(m_CBSaveByID[i], 0, wxEXPAND | wxALL, 3);
m_gGenSettingsID[i]->Add(m_CBShowAdvanced[i], 0, wxEXPAND | wxALL, 3); m_gGenSettingsID[i]->Add(m_CBShowAdvanced[i], 0, wxEXPAND | wxALL, 3);
// Create objects for Rumble settings (general 4)
m_RStrength[i] = new wxComboBox(m_Controller[i], IDC_RUMBLESTRENGTH, wxAS_RumbleStrength[0], wxDefaultPosition, wxSize(85, 20), wxAS_RumbleStrength, wxCB_READONLY);
m_Rumble[i] = new wxCheckBox(m_Controller[i], IDC_ENABLERUMBLE, wxT("Enable Rumble"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
// Populate general settings 4
m_gRumble[i] = new wxStaticBoxSizer( wxVERTICAL, m_Controller[i], wxT("Rumble Settings"));
m_gGBRumble[i] = new wxGridBagSizer(0, 0);
m_gGBRumble[i]->Add(m_Rumble[i], wxGBPosition(0, 0), wxGBSpan(1, 1), (wxTOP), 1);
m_gGBRumble[i]->Add(m_RStrength[i], wxGBPosition(1, 0), wxGBSpan(1, 1), (wxTOP), 6);
m_gRumble[i]->Add(m_gGBRumble[i], 0, wxEXPAND | wxALL, 3);
// Create tooltips // Create tooltips
m_ControlType[i]->SetToolTip(wxT( m_ControlType[i]->SetToolTip(wxT(
"Use a 'hat' on your gamepad or configure a custom button for each direction." "Use a 'hat' on your gamepad or configure a custom button for each direction."
@ -899,6 +926,8 @@ void ConfigBox::CreateGUIControls()
m_sSettings[i]->Add(m_gExtrasettings[i], 0, wxEXPAND | wxALL, 0); m_sSettings[i]->Add(m_gExtrasettings[i], 0, wxEXPAND | wxALL, 0);
m_sSettings[i]->Add(m_gGenSettings[i], 0, wxEXPAND | wxLEFT, 5); m_sSettings[i]->Add(m_gGenSettings[i], 0, wxEXPAND | wxLEFT, 5);
m_sSettings[i]->Add(m_gGenSettingsID[i], 0, wxEXPAND | wxLEFT, 5); m_sSettings[i]->Add(m_gGenSettingsID[i], 0, wxEXPAND | wxLEFT, 5);
m_sSettings[i]->Add(m_gRumble[i], 0, wxEXPAND | wxLEFT, 5);
// ------------------------- // -------------------------
//////////////////////////// General settings //////////////////////////// General settings

View File

@ -112,17 +112,22 @@ class ConfigBox : public wxDialog
wxStaticBoxSizer *m_gGenSettings[4]; wxStaticBoxSizer *m_gGenSettings[4];
wxStaticBoxSizer *m_gGenSettingsID[4]; wxStaticBoxSizer *m_gGenSettingsID[4];
wxGridBagSizer * m_gGBGenSettings[4]; wxGridBagSizer *m_gGBGenSettings[4];
wxCheckBox *m_CBSaveByID[4], *m_CBShowAdvanced[4]; wxCheckBox *m_CBSaveByID[4], *m_CBShowAdvanced[4];
wxStaticText *m_TSControltype[4], *m_TSTriggerType[4]; wxStaticText *m_TSControltype[4], *m_TSTriggerType[4];
wxStaticBoxSizer *m_gStatusIn[4], *m_gStatusInSettings[4], *m_gStatusAdvancedSettings[4]; // Advanced settings wxStaticBoxSizer *m_gStatusIn[4], *m_gStatusInSettings[4], *m_gStatusAdvancedSettings[4]; // Advanced settings
wxBoxSizer *m_gStatusInSettingsH[4]; wxBoxSizer *m_gStatusInSettingsH[4];
wxGridBagSizer * m_GBAdvancedMainStick[4]; wxGridBagSizer *m_GBAdvancedMainStick[4];
wxStaticText *m_TStatusIn[4], *m_TStatusOut[4], *m_STDiagonal[4]; wxStaticText *m_TStatusIn[4], *m_TStatusOut[4], *m_STDiagonal[4];
wxComboBox *m_CoBDiagonal[4]; wxCheckBox *m_CBS_to_C[4]; wxComboBox *m_CoBDiagonal[4]; wxCheckBox *m_CBS_to_C[4];
wxCheckBox *m_CBCheckFocus[4], *m_AdvancedMapFilter[4]; wxCheckBox *m_CBCheckFocus[4], *m_AdvancedMapFilter[4];
wxCheckBox *m_Rumble[4]; // Rumble settings
wxComboBox *m_RStrength[4];
wxStaticBoxSizer *m_gRumble[4];
wxGridBagSizer *m_gGBRumble[4];
wxStaticBoxSizer *m_gStatusTriggers[4]; // Triggers wxStaticBoxSizer *m_gStatusTriggers[4]; // Triggers
wxStaticText *m_TStatusTriggers[4]; wxStaticText *m_TStatusTriggers[4];
@ -219,6 +224,8 @@ class ConfigBox : public wxDialog
IDC_SAVEBYID, IDC_SHOWADVANCED, // Settings IDC_SAVEBYID, IDC_SHOWADVANCED, // Settings
IDC_ENABLERUMBLE, IDC_RUMBLESTRENGTH, IDT_RUMBLESTRENGTH, // Rumble
ID_INSTATUS1, ID_INSTATUS2, ID_INSTATUS3, ID_INSTATUS4, // Advanced status ID_INSTATUS1, ID_INSTATUS2, ID_INSTATUS3, ID_INSTATUS4, // Advanced status
ID_STATUSBMP1, ID_STATUSBMP2, ID_STATUSBMP3, ID_STATUSBMP4, ID_STATUSBMP1, ID_STATUSBMP2, ID_STATUSBMP3, ID_STATUSBMP4,
ID_STATUSDOTBMP1, ID_STATUSDOTBMP2, ID_STATUSDOTBMP3, ID_STATUSDOTBMP4, ID_STATUSDOTBMP1, ID_STATUSDOTBMP2, ID_STATUSDOTBMP3, ID_STATUSDOTBMP4,

View File

@ -80,11 +80,12 @@ void ConfigBox::UpdateGUIButtonMapping(int controller)
m_CoBDiagonal[controller]->SetValue(wxString::FromAscii(PadMapping[controller].SDiagonal.c_str())); m_CoBDiagonal[controller]->SetValue(wxString::FromAscii(PadMapping[controller].SDiagonal.c_str()));
m_CBS_to_C[controller]->SetValue(PadMapping[controller].bSquareToCircle); m_CBS_to_C[controller]->SetValue(PadMapping[controller].bSquareToCircle);
m_AdvancedMapFilter[controller]->SetValue(g_Config.bNoTriggerFilter); m_AdvancedMapFilter[controller]->SetValue(g_Config.bNoTriggerFilter);
// Update Rumble checkbox
m_Rumble[controller]->SetValue(PadMapping[controller].rumble);
#ifdef RERECORDING #ifdef RERECORDING
m_CheckRecording[controller]->SetValue(g_Config.bRecording); m_CheckRecording[controller]->SetValue(g_Config.bRecording);
m_CheckPlayback[controller]->SetValue(g_Config.bPlayback); m_CheckPlayback[controller]->SetValue(g_Config.bPlayback);
#endif #endif
//LogMsg("m_TriggerType[%i] = %i\n", controller, PadMapping[controller].triggertype);
// Update D-Pad // Update D-Pad
if(PadMapping[controller].controllertype == InputCommon::CTL_DPAD_HAT) if(PadMapping[controller].controllertype == InputCommon::CTL_DPAD_HAT)
@ -99,8 +100,6 @@ void ConfigBox::UpdateGUIButtonMapping(int controller)
tmp << PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_RIGHT]; m_JoyDpadRight[controller]->SetValue(tmp); tmp.clear(); tmp << PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_RIGHT]; m_JoyDpadRight[controller]->SetValue(tmp); tmp.clear();
} }
// Replace "-1" with "" in the GUI controls
//if(ControlsCreated) ToBlank();
} }
/* Populate the PadMapping array with the dialog items settings (for example /* Populate the PadMapping array with the dialog items settings (for example

View File

@ -37,32 +37,29 @@
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Enable or disable rumble. Set USE_RUMBLE_DINPUT_HACK in nJoy.h // Enable or disable rumble.
// ¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯
#ifdef USE_RUMBLE_DINPUT_HACK
bool g_rumbleEnable = FALSE;
#endif
// Rumble in windows // Rumble in windows
#ifdef _WIN32 #ifdef _WIN32
#ifdef USE_RUMBLE_DINPUT_HACK struct RUMBLE // GC Pad rumble DIDevice
LPDIRECTINPUT8 g_pDI = NULL; {
LPDIRECTINPUTDEVICE8 g_pDevice = NULL; LPDIRECTINPUTDEVICE8 g_pDevice; // 4 pads objects
LPDIRECTINPUTEFFECT g_pEffect = NULL; LPDIRECTINPUTEFFECT g_pEffect;
DWORD g_dwNumForceFeedbackAxis;
DWORD g_dwNumForceFeedbackAxis = 0; DIEFFECT eff;
INT g_nXForce = 0; };
INT g_nYForce = 0;
#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } } #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
HRESULT InitDirectInput(HWND hDlg);
//VOID FreeDirectInput();
BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext); BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext);
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext); BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext);
HRESULT SetDeviceForcesXY(); void SetDeviceForcesXY(int pad, int nXYForce);
#endif
LPDIRECTINPUT8 g_Rumble; // DInput Rumble object
RUMBLE pRumble[4]; // 4 GC Rumble Pads
extern InputCommon::CONTROLLER_MAPPING PadMapping[4];
#elif defined(__linux__) #elif defined(__linux__)
#include <sys/types.h> #include <sys/types.h>
@ -74,101 +71,36 @@ bool g_rumbleEnable = FALSE;
struct ff_effect effect; struct ff_effect effect;
bool CanRumble = false; bool CanRumble = false;
#endif #endif
////////////////////// //////////////////////
// Set PAD rumble. Explanation: Stop = 0, Rumble = 1
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
{
//if (_numPAD > 0)
// return;
// SDL can't rumble the gamepad so we need to use platform specific code
#ifdef _WIN32
#ifdef USE_RUMBLE_DINPUT_HACK
static int a = 0;
if ((_uType == 0) || (_uType == 2))
{
a = 0;
}
else if (_uType == 1)
{
a = _uStrength > 2 ? 8000 : 0;
}
a = int ((float)a * 0.96f);
if (!g_rumbleEnable)
{
a = 0;
}
else
{
g_nYForce = a;
SetDeviceForcesXY();
}
#endif
#elif defined(__linux__)
struct input_event event;
if (CanRumble)
{
if (_uType == 1)
{
event.type = EV_FF;
event.code = effect.id;
event.value = 1;
if (write(fd, (const void*) &event, sizeof(event)) == -1) {
perror("Play effect");
exit(1);
}
}
if ((_uType == 0) || (_uType == 2))
{
event.type = EV_FF;
event.code = effect.id;
event.value = 0;
if (write(fd, (const void*) &event, sizeof(event)) == -1) {
perror("Stop effect");
exit(1);
}
}
}
#endif
}
// Use PAD rumble // Use PAD rumble
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus)
void Pad_Use_Rumble(u8 _numPAD)//, SPADStatus* _pPADStatus)
{ {
#ifdef _WIN32 #ifdef _WIN32
#ifdef USE_RUMBLE_DINPUT_HACK
// Enable or disable rumble if (PadMapping[_numPAD].rumble) {
if (PadState[_numPAD].halfpress) if (!g_Rumble) {
if (!g_pDI)
if (FAILED(InitDirectInput(m_hWnd))) HWND rumble_hWnd = GetParent(m_hWnd);
{ HWND TopLevel = GetParent(rumble_hWnd);
MessageBox(NULL, SDL_GetError(), "Could not initialize DirectInput!", MB_ICONERROR);
g_rumbleEnable = FALSE; // Support both rendering to main window and not.
//return; if (GetForegroundWindow() == TopLevel)
rumble_hWnd = TopLevel;
if (GetForegroundWindow() == m_hWnd)
rumble_hWnd = m_hWnd;
if (FAILED(InitRumble(rumble_hWnd)))
PanicAlert("Could not initialize Rumble!");
} else {
// Acquire gamepad
if (pRumble[_numPAD].g_pDevice != NULL)
pRumble[_numPAD].g_pDevice->Acquire();
} }
else
{
g_rumbleEnable = TRUE;
} }
if (g_rumbleEnable)
{
g_pDevice->Acquire();
if (g_pEffect) g_pEffect->Start(1, 0);
}
#endif
#elif defined(__linux__) #elif defined(__linux__)
if (!fd) if (!fd)
{ {
@ -204,191 +136,257 @@ void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus)
#endif #endif
} }
////////////////////////////////////////////////////
// Set PAD rumble. Explanation: Stop = 0, Rumble = 1
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
{
Pad_Use_Rumble(_numPAD);
// SDL can't rumble the gamepad so we need to use platform specific code
#ifdef _WIN32
int a = 0;
if (_uType == 1)
{
// it looks like _uStrength is equal to 3 everytime anyway...
a = _uStrength > 2 ? (1000*(g_Config.RumbleStrength + 1)) : 0;
a = a > 10000 ? 10000 : a;
}
// a = int ((float)a * 0.96f);
// What is this for ?
// else if ((_uType == 0) || (_uType == 2))
if (PadMapping[_numPAD].rumble) // rumble activated
{
// Start Effect
SetDeviceForcesXY(_numPAD, a);
}
#elif defined(__linux__)
struct input_event event;
if (CanRumble)
{
if (_uType == 1)
{
event.type = EV_FF;
event.code = effect.id;
event.value = 1;
if (write(fd, (const void*) &event, sizeof(event)) == -1) {
perror("Play effect");
exit(1);
}
}
if ((_uType == 0) || (_uType == 2))
{
event.type = EV_FF;
event.code = effect.id;
event.value = 0;
if (write(fd, (const void*) &event, sizeof(event)) == -1) {
perror("Stop effect");
exit(1);
}
}
}
#endif
}
#ifdef _WIN32 #ifdef _WIN32
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Rumble stuff :D! // Rumble stuff :D!
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// //
#ifdef USE_RUMBLE_DINPUT_HACK
HRESULT InitDirectInput( HWND hDlg ) HRESULT InitRumble(HWND hWnd)
{ {
DIPROPDWORD dipdw; DIPROPDWORD dipdw;
HRESULT hr; HRESULT hr;
// Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use. // Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use.
if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_pDI, NULL))) if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_Rumble, NULL)))
{
return hr;
}
// Look for a force feedback device we can use
if (FAILED(hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, NULL, DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK)))
{
return hr;
}
if (NULL == g_pDevice)
{
MessageBox(NULL, "Force feedback device not found. nJoy will now disable rumble." ,"FFConst" , MB_ICONERROR | MB_OK);
g_rumbleEnable = FALSE;
return S_OK;
}
// Set the data format to "simple joystick" - a predefined data format. A
// data format specifies which controls on a device we are interested in,
// and how they should be reported.
//
// This tells DirectInput that we will be passing a DIJOYSTATE structure to
// IDirectInputDevice8::GetDeviceState(). Even though we won't actually do
// it in this sample. But setting the data format is important so that the
// DIJOFS_* values work properly.
if (FAILED(hr = g_pDevice->SetDataFormat(&c_dfDIJoystick)))
return hr; return hr;
// Set the cooperative level to let DInput know how this device should // Look for a device we can use
// interact with the system and with other DInput applications. if (FAILED(hr = g_Rumble->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, NULL, DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK)))
// Exclusive access is required in order to perform force feedback.
//if (FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
if (FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
{
return hr; return hr;
}
// Since we will be playing force feedback effects, we should disable the for (int i=0; i<4; i++)
// auto-centering spring. {
if (NULL == pRumble[i].g_pDevice)
PadMapping[i].rumble = false; // Disable Rumble for this pad only.
else
{
pRumble[i].g_pDevice->SetDataFormat(&c_dfDIJoystick);
pRumble[i].g_pDevice->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND);
// Request exclusive acces for both background and foreground.
dipdw.diph.dwSize = sizeof(DIPROPDWORD); dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0; dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE; dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = FALSE; dipdw.dwData = FALSE;
if (FAILED(hr = g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph))) // if Force Feedback doesn't seem to work...
return hr; if (FAILED(pRumble[i].g_pDevice->EnumObjects(EnumAxesCallback,
(void*)&pRumble[i].g_dwNumForceFeedbackAxis, DIDFT_AXIS))
// Enumerate and count the axes of the joystick || FAILED(pRumble[i].g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph)))
if (FAILED(hr = g_pDevice->EnumObjects(EnumAxesCallback, (VOID*)&g_dwNumForceFeedbackAxis, DIDFT_AXIS)))
return hr;
// This simple sample only supports one or two axis joysticks
if (g_dwNumForceFeedbackAxis > 2)
g_dwNumForceFeedbackAxis = 2;
// This application needs only one effect: Applying raw forces.
DWORD rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y};
LONG rglDirection[2] = {0, 0};
DICONSTANTFORCE cf = {0};
DIEFFECT eff;
ZeroMemory(&eff, sizeof(eff));
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 = g_dwNumForceFeedbackAxis;
eff.rgdwAxes = rgdwAxes;
eff.rglDirection = rglDirection;
eff.lpEnvelope = 0;
eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE );
eff.lpvTypeSpecificParams = &cf;
eff.dwStartDelay = 0;
// Create the prepared effect
if (FAILED(hr = g_pDevice->CreateEffect(GUID_ConstantForce, &eff, &g_pEffect, NULL)))
{ {
return hr; PanicAlert("Device %d doesn't seem to work ! \nRumble for device %d is now Disabled !", i+1);
PadMapping[i].rumble = false; // Disable Rumble for this pad
continue; // Next pad
} }
if (NULL == g_pEffect) if (pRumble[i].g_dwNumForceFeedbackAxis > 2)
pRumble[i].g_dwNumForceFeedbackAxis = 2;
DWORD _rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y};
long rglDirection[2] = {0, 0};
DICONSTANTFORCE cf = {0};
ZeroMemory(&pRumble[i].eff, sizeof(pRumble[i].eff));
pRumble[i].eff.dwSize = sizeof(DIEFFECT);
pRumble[i].eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
pRumble[i].eff.dwDuration = INFINITE; // fixed time may be safer (X * DI_SECONDS)
pRumble[i].eff.dwSamplePeriod = 0;
pRumble[i].eff.dwGain = DI_FFNOMINALMAX;
pRumble[i].eff.dwTriggerButton = DIEB_NOTRIGGER;
pRumble[i].eff.dwTriggerRepeatInterval = 0;
pRumble[i].eff.cAxes = pRumble[i].g_dwNumForceFeedbackAxis;
pRumble[i].eff.rgdwAxes = _rgdwAxes;
pRumble[i].eff.rglDirection = rglDirection;
pRumble[i].eff.lpEnvelope = 0;
pRumble[i].eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE );
pRumble[i].eff.lpvTypeSpecificParams = &cf;
pRumble[i].eff.dwStartDelay = 0;
// Create the prepared effect
if (FAILED(hr = pRumble[i].g_pDevice->CreateEffect(GUID_ConstantForce, &pRumble[i].eff, &pRumble[i].g_pEffect, NULL)))
return hr;
if (pRumble[i].g_pEffect == NULL)
return E_FAIL; return E_FAIL;
}
}
return S_OK; return S_OK;
} }
VOID FreeDirectInput() void SetDeviceForcesXY(int npad, int nXYForce)
{ {
// Unacquire the device one last time just in case // Security check
// the app tried to exit while the device is still acquired. if (pRumble[npad].g_pDevice == NULL)
if (g_pDevice) return;
g_pDevice->Unacquire();
// Release any DirectInput objects. // If nXYForce is null, there's no point to create the effect
SAFE_RELEASE(g_pEffect); // Just stop the force feedback
SAFE_RELEASE(g_pDevice); if (nXYForce == 0) {
SAFE_RELEASE(g_pDI); pRumble[npad].g_pEffect->Stop();
return;
}
long rglDirection[2] = {0};
DICONSTANTFORCE cf;
// If only one force feedback axis, then apply only one direction and keep the direction at zero
if (pRumble[npad].g_dwNumForceFeedbackAxis == 1)
{
rglDirection[0] = 0;
cf.lMagnitude = nXYForce; // max should be 10000
}
// If two force feedback axis, then apply magnitude from both directions
else
{
rglDirection[0] = nXYForce;
rglDirection[1] = nXYForce;
cf.lMagnitude = 1.4142f*nXYForce;
}
ZeroMemory(&pRumble[npad].eff, sizeof(pRumble[npad].eff));
pRumble[npad].eff.dwSize = sizeof(DIEFFECT);
pRumble[npad].eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
pRumble[npad].eff.cAxes = pRumble[npad].g_dwNumForceFeedbackAxis;
pRumble[npad].eff.rglDirection = rglDirection;
pRumble[npad].eff.lpEnvelope = 0;
pRumble[npad].eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
pRumble[npad].eff.lpvTypeSpecificParams = &cf;
pRumble[npad].eff.dwStartDelay = 0;
// Now set the new parameters..
pRumble[npad].g_pEffect->SetParameters(&pRumble[npad].eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START);
// ..And start the effect immediately.
if (pRumble[npad].g_pEffect != NULL)
pRumble[npad].g_pEffect->Start(1, 0);
} }
BOOL CALLBACK EnumFFDevicesCallback( const DIDEVICEINSTANCE* pInst, VOID* pContext ) BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext)
{ {
LPDIRECTINPUTDEVICE8 pDevice; LPDIRECTINPUTDEVICE8 pDevice;
DIPROPDWORD dipdw;
HRESULT hr; HRESULT hr;
// Obtain an interface to the enumerated force feedback device. int JoystickID;
hr = g_pDI->CreateDevice(pInst->guidInstance, &pDevice, NULL);
// If it failed, then we can't use this device for some bizarre reason. dipdw.diph.dwSize = sizeof(DIPROPDWORD);
// (Maybe the user unplugged it while we were in the middle of enumerating it.) So continue enumerating dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
if (FAILED(hr)) dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
g_Rumble->CreateDevice(pInst->guidInstance, &pDevice, NULL); // Create a DInput pad device
if (SUCCEEDED(hr = pDevice->GetProperty(DIPROP_JOYSTICKID, &dipdw.diph))) // Get DInput Device ID
JoystickID = dipdw.dwData;
else
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
// We successfully created an IDirectInputDevice8. So stop looking for another one. //PanicAlert("DInput ID : %d \nSDL ID (1-4) : %d / %d / %d / %d\n", JoystickID, PadMapping[0].ID, PadMapping[1].ID, PadMapping[2].ID, PadMapping[3].ID);
g_pDevice = pDevice;
return DIENUM_STOP; for (int i=0; i<4; i++)
{
if (PadMapping[i].ID == JoystickID) // if SDL ID = DInput ID -> we're dealing with the same device
{
// a DInput device is created even if rumble is disabled on startup
// this way, you can toggle the rumble setting while in game
if (PadMapping[i].enabled) // && PadMapping[i].rumble
{
pRumble[i].g_pDevice = pDevice; // everything looks good, save the DInput device
}
}
}
return DIENUM_CONTINUE;
} }
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext) BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext)
{ {
DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; // Enum Rumble Axis
if ((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0) if ((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0)
(*pdwNumForceFeedbackAxis)++; (*pdwNumForceFeedbackAxis)++;
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
} }
HRESULT SetDeviceForcesXY() VOID FreeDirectInput()
{ {
// Modifying an effect is basically the same as creating a new one, except you need only specify the parameters you are modifying // Unacquire the device one last time just in case
LONG rglDirection[2] = { 0, 0 }; // the app tried to exit while the device is still acquired.
DICONSTANTFORCE cf; for (int i=0; i<4; i++) // Free all pads
if (g_dwNumForceFeedbackAxis == 1)
{ {
// If only one force feedback axis, then apply only one direction and keep the direction at zero if (pRumble[i].g_pDevice) {
cf.lMagnitude = g_nXForce; pRumble[i].g_pEffect->Stop();
rglDirection[0] = 0; pRumble[i].g_pDevice->Unacquire();
}
else
{
// If two force feedback axis, then apply magnitude from both directions
rglDirection[0] = g_nXForce;
rglDirection[1] = g_nYForce;
cf.lMagnitude = (DWORD)sqrt((double)g_nXForce * (double)g_nXForce + (double)g_nYForce * (double)g_nYForce );
} }
DIEFFECT eff; SAFE_RELEASE(pRumble[i].g_pEffect);
ZeroMemory(&eff, sizeof(eff)); SAFE_RELEASE(pRumble[i].g_pDevice);
eff.dwSize = sizeof(DIEFFECT); }
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
eff.cAxes = g_dwNumForceFeedbackAxis;
eff.rglDirection = rglDirection;
eff.lpEnvelope = 0;
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
eff.lpvTypeSpecificParams = &cf;
eff.dwStartDelay = 0;
// Now set the new parameters and start the effect immediately. SAFE_RELEASE(g_Rumble); // Rumble object
return g_pEffect->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START);
} }
#endif
#endif #endif

View File

@ -6,7 +6,7 @@
// //
// Author: Falcon4ever (nJoy@falcon4ever.com) // Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net // Site: www.multigesture.net
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// //
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// //
@ -38,6 +38,7 @@
The StrangeHack in ConfigAdvanced.cpp doesn't work in Linux, it still wont resize the The StrangeHack in ConfigAdvanced.cpp doesn't work in Linux, it still wont resize the
window correctly. So currently in Linux you have to have advanced controls enabled when window correctly. So currently in Linux you have to have advanced controls enabled when
you open the window to see them. you open the window to see them.
// TODO : we should not need a Hack in the first place :/
////////////////////////*/ ////////////////////////*/
@ -80,7 +81,6 @@
// Variables // Variables
// ¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯
// Rumble in windows
#define _EXCLUDE_MAIN_ // Avoid certain declarations in nJoy.h #define _EXCLUDE_MAIN_ // Avoid certain declarations in nJoy.h
FILE *pFile; FILE *pFile;
HINSTANCE nJoy_hInst = NULL; HINSTANCE nJoy_hInst = NULL;
@ -96,13 +96,10 @@ SPADInitialize *g_PADInitialize = NULL;
PLUGIN_GLOBALS* globals = NULL; PLUGIN_GLOBALS* globals = NULL;
// Rumble // Rumble
#ifdef _WIN32 #if defined(__linux__)
#elif defined(__linux__)
extern int fd; extern int fd;
#endif #endif
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// wxWidgets // wxWidgets
// ¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯
@ -250,14 +247,14 @@ void Initialize(void *init)
g_PADInitialize = (SPADInitialize*)init; g_PADInitialize = (SPADInitialize*)init;
g_EmulatorRunning = true; g_EmulatorRunning = true;
#ifdef _DEBUG
DEBUG_INIT();
#endif
#ifdef _WIN32 #ifdef _WIN32
m_hWnd = (HWND)g_PADInitialize->hWnd; m_hWnd = (HWND)g_PADInitialize->hWnd;
#endif #endif
#ifdef _DEBUG
DEBUG_INIT();
#endif
// Populate joyinfo for all attached devices if the configuration window is not already open // Populate joyinfo for all attached devices if the configuration window is not already open
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
if(!m_frame) if(!m_frame)
@ -327,9 +324,7 @@ void Shutdown()
g_PADInitialize = NULL; g_PADInitialize = NULL;
#ifdef _WIN32 #ifdef _WIN32
#ifdef USE_RUMBLE_DINPUT_HACK
FreeDirectInput(); FreeDirectInput();
#endif
#elif defined(__linux__) #elif defined(__linux__)
close(fd); close(fd);
#endif #endif
@ -415,6 +410,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
return; return;
} }
#endif #endif
// ---------------------- // ----------------------
// Clear pad status // Clear pad status
@ -426,6 +422,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// Get type // Get type
int TriggerType = PadMapping[_numPAD].triggertype; int TriggerType = PadMapping[_numPAD].triggertype;
int TriggerValue = PadState[_numPAD].halfpress ? 100 : 255;
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
// The analog controls // The analog controls
@ -440,7 +437,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
int TriggerRight = PadState[_numPAD].axis[InputCommon::CTL_R_SHOULDER]; int TriggerRight = PadState[_numPAD].axis[InputCommon::CTL_R_SHOULDER];
// Check if we should make adjustments // Check if we should make adjustments
if(PadMapping[_numPAD].bSquareToCircle) if (PadMapping[_numPAD].bSquareToCircle)
{ {
std::vector<int> main_xy = InputCommon::Square2Circle(i_main_stick_x, i_main_stick_y, _numPAD, PadMapping[_numPAD].SDiagonal); std::vector<int> main_xy = InputCommon::Square2Circle(i_main_stick_x, i_main_stick_y, _numPAD, PadMapping[_numPAD].SDiagonal);
i_main_stick_x = main_xy.at(0); i_main_stick_x = main_xy.at(0);
@ -454,54 +451,61 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
u8 sub_stick_y = InputCommon::Pad_Convert(i_sub_stick_y); u8 sub_stick_y = InputCommon::Pad_Convert(i_sub_stick_y);
// Convert the triggers values, if we are using analog triggers at all // Convert the triggers values, if we are using analog triggers at all
if(PadMapping[_numPAD].triggertype == InputCommon::CTL_TRIGGER_SDL) if (PadMapping[_numPAD].triggertype == InputCommon::CTL_TRIGGER_SDL)
{ {
if(PadMapping[_numPAD].buttons[InputCommon::CTL_L_SHOULDER] >= 1000) TriggerLeft = InputCommon::Pad_Convert(TriggerLeft); if (PadMapping[_numPAD].buttons[InputCommon::CTL_L_SHOULDER] >= 1000) TriggerLeft = InputCommon::Pad_Convert(TriggerLeft);
if(PadMapping[_numPAD].buttons[InputCommon::CTL_R_SHOULDER] >= 1000) TriggerRight = InputCommon::Pad_Convert(TriggerRight); if (PadMapping[_numPAD].buttons[InputCommon::CTL_R_SHOULDER] >= 1000) TriggerRight = InputCommon::Pad_Convert(TriggerRight);
} }
// Set Deadzones (perhaps out of function?) // Set Deadzone
int deadzone = (int)(((float)(128.00/100.00)) * (float)(PadMapping[_numPAD].deadzone + 1)); float deadzone = (128.00 * (float)(PadMapping[_numPAD].deadzone + 1.00)) / 100.00;
int deadzone2 = (int)(((float)(-128.00/100.00)) * (float)(PadMapping[_numPAD].deadzone + 1)); float distance_main = (float)sqrt((float)(main_stick_x * main_stick_x) + (float)(main_stick_y * main_stick_y));
float distance_sub = (float)sqrt((float)(sub_stick_x * sub_stick_x) + (float)(sub_stick_y * sub_stick_y));
// Send values to Dolpin if they are outside the deadzone // Send values to Dolpin if they are outside the deadzone
if ((main_stick_x < deadzone2) || (main_stick_x > deadzone)) _pPADStatus->stickX = main_stick_x; if (distance_main > deadzone)
if ((main_stick_y < deadzone2) || (main_stick_y > deadzone)) _pPADStatus->stickY = main_stick_y; {
if ((sub_stick_x < deadzone2) || (sub_stick_x > deadzone)) _pPADStatus->substickX = sub_stick_x; _pPADStatus->stickX = main_stick_x;
if ((sub_stick_y < deadzone2) || (sub_stick_y > deadzone)) _pPADStatus->substickY = sub_stick_y; _pPADStatus->stickY = main_stick_y;
}
if (distance_sub > deadzone)
{
_pPADStatus->substickX = sub_stick_x;
_pPADStatus->substickY = sub_stick_y;
}
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
// The L and R triggers // The L and R triggers
// ----------- // -----------
int TriggerValue = 255;
if (PadState[_numPAD].halfpress) TriggerValue = 100;
_pPADStatus->button |= PAD_USE_ORIGIN; // Neutral value, no button pressed // Neutral value, no button pressed
_pPADStatus->button |= PAD_USE_ORIGIN;
// Check if the digital L button is pressed // Check if the digital L button is pressed
if (PadState[_numPAD].buttons[InputCommon::CTL_L_SHOULDER]) if (PadState[_numPAD].buttons[InputCommon::CTL_L_SHOULDER])
{ {
if (!PadState[_numPAD].halfpress)
_pPADStatus->button |= PAD_TRIGGER_L; _pPADStatus->button |= PAD_TRIGGER_L;
_pPADStatus->triggerLeft = TriggerValue; _pPADStatus->triggerLeft = TriggerValue;
} }
// no the digital L button is not pressed, but the analog left trigger is // no the digital L button is not pressed, but the analog left trigger is
else if(TriggerLeft > 0) else if (TriggerLeft > 0)
_pPADStatus->triggerLeft = TriggerLeft; _pPADStatus->triggerLeft = TriggerLeft;
// Check if the digital R button is pressed // Check if the digital R button is pressed
if (PadState[_numPAD].buttons[InputCommon::CTL_R_SHOULDER]) if (PadState[_numPAD].buttons[InputCommon::CTL_R_SHOULDER])
{ {
if (!PadState[_numPAD].halfpress)
_pPADStatus->button |= PAD_TRIGGER_R; _pPADStatus->button |= PAD_TRIGGER_R;
_pPADStatus->triggerRight = TriggerValue; _pPADStatus->triggerRight = TriggerValue;
} }
// no the digital R button is not pressed, but the analog right trigger is // no the digital R button is not pressed, but the analog right trigger is
else if(TriggerRight > 0) else if (TriggerRight > 0)
_pPADStatus->triggerRight = TriggerRight; _pPADStatus->triggerRight = TriggerRight;
// Update the buttons in analog mode to // Update the buttons in analog mode too
if(TriggerLeft == 0xff) _pPADStatus->button |= PAD_TRIGGER_L; if (TriggerLeft > 0xf0) _pPADStatus->button |= PAD_TRIGGER_L;
if(TriggerRight == 0xff) _pPADStatus->button |= PAD_TRIGGER_R; if (TriggerRight > 0xf0) _pPADStatus->button |= PAD_TRIGGER_R;
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
@ -548,9 +552,6 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// Update error code // Update error code
_pPADStatus->err = PAD_ERR_NONE; _pPADStatus->err = PAD_ERR_NONE;
// Use rumble
Pad_Use_Rumble(_numPAD, _pPADStatus);
// ------------------------------------------- // -------------------------------------------
// Rerecording // Rerecording
// ---------------------- // ----------------------

View File

@ -33,15 +33,6 @@
#ifndef __NJOY_h__ #ifndef __NJOY_h__
#define __NJOY_h__ #define __NJOY_h__
//////////////////////////////////////////////////////////////////////////////////////////
// Settings
// ¯¯¯¯¯¯¯¯¯¯
// Set this if you want to use the rumble 'hack' for controller one
//#define USE_RUMBLE_DINPUT_HACK
//////////////////////////
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Includes // Includes
// ¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯
@ -71,13 +62,12 @@
#define DIRECTINPUT_VERSION 0x0800 #define DIRECTINPUT_VERSION 0x0800
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#ifdef USE_RUMBLE_DINPUT_HACK
#pragma comment(lib, "dxguid.lib") #pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dinput8.lib") #pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "winmm.lib") #pragma comment(lib, "winmm.lib")
#include <dinput.h> #include <dinput.h>
VOID FreeDirectInput(); // Needed in both nJoy.cpp and Rumble.cpp void FreeDirectInput(); // Needed in both nJoy.cpp and Rumble.cpp
#endif
#endif // _WIN32 #endif // _WIN32
#ifdef _WIN32 #ifdef _WIN32
@ -142,11 +132,10 @@ void DEBUG_INIT();
void DEBUG_QUIT(); void DEBUG_QUIT();
bool IsFocus(); bool IsFocus();
bool ReloadDLL(); bool ReloadDLL();
#ifdef _WIN32
HRESULT InitRumble(HWND hWnd);
#endif
void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus); // Rumble
//void SaveConfig();
//void LoadConfig();
//////////////////////////////// ////////////////////////////////