mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-25 18:35:37 +00:00
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:
parent
e24e2db1a1
commit
b0852c1bef
@ -92,6 +92,7 @@ struct CONTROLLER_MAPPING // GC PAD MAPPING
|
||||
int triggertype; // Triggers range
|
||||
std::string SDiagonal;
|
||||
bool bSquareToCircle;
|
||||
bool rumble;
|
||||
int eventnum; // Linux Event Number, Can't be found dynamically yet
|
||||
};
|
||||
|
||||
|
@ -271,13 +271,15 @@ void DInput_Read(int _numPAD, SPADStatus* _pPADStatus)
|
||||
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_L]] & 0xFF)
|
||||
{
|
||||
_pPADStatus->button |= PAD_TRIGGER_L;
|
||||
if (triggervalue > 230)
|
||||
_pPADStatus->button |= PAD_TRIGGER_L;
|
||||
_pPADStatus->triggerLeft = triggervalue;
|
||||
}
|
||||
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_R]] & 0xFF)
|
||||
{
|
||||
_pPADStatus->button |= PAD_TRIGGER_R;
|
||||
if (triggervalue > 230)
|
||||
_pPADStatus->button |= PAD_TRIGGER_R;
|
||||
_pPADStatus->triggerRight = triggervalue;
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,7 @@ void Config::Save(int Slot)
|
||||
file.Set("General", "SaveByID", g_Config.bSaveByID);
|
||||
file.Set("General", "CheckForFocus", g_Config.bCheckFocus);
|
||||
file.Set("General", "NoTriggerFilter", g_Config.bNoTriggerFilter);
|
||||
file.Set("General", "RumbleStrength", g_Config.RumbleStrength);
|
||||
#ifdef RERECORDING
|
||||
file.Set("General", "Recording", g_Config.bRecording);
|
||||
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(), "TriggerType", PadMapping[i].triggertype);
|
||||
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(), "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", "CheckForFocus", &g_Config.bCheckFocus, false);
|
||||
file.Get("General", "NoTriggerFilter", &g_Config.bNoTriggerFilter, false);
|
||||
file.Get("General", "RumbleStrength", &g_Config.RumbleStrength, 8);
|
||||
#ifdef RERECORDING
|
||||
file.Get("General", "Recording", &g_Config.bRecording, 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(), "TriggerType", &PadMapping[i].triggertype, 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(), "SquareToCircle", &Tmp, false); PadMapping[i].bSquareToCircle = Tmp;
|
||||
|
@ -30,6 +30,7 @@ struct Config
|
||||
bool bSaveByID;
|
||||
bool bCheckFocus;
|
||||
bool bNoTriggerFilter;
|
||||
int RumbleStrength;
|
||||
#ifdef RERECORDING
|
||||
bool bRecording;
|
||||
bool bPlayback;
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
// Author: Falcon4ever (nJoy@falcon4ever.com)
|
||||
// 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_DEADZONE, ConfigBox::ChangeSettings)
|
||||
|
||||
// Rumble settings
|
||||
EVT_CHECKBOX(IDC_ENABLERUMBLE, ConfigBox::ChangeSettings)
|
||||
EVT_COMBOBOX(IDC_RUMBLESTRENGTH, ConfigBox::ChangeSettings)
|
||||
|
||||
// Advanced settings
|
||||
EVT_COMBOBOX(IDCB_MAINSTICK_DIAGONAL, 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)
|
||||
{
|
||||
DoSave(); // Save settings
|
||||
//g_Config.Load(); // Reload settings to PadMapping
|
||||
if(Debugging) PanicAlert("Done");
|
||||
Close(); // Call OnClose()
|
||||
}
|
||||
@ -217,7 +220,6 @@ void ConfigBox::CancelClick(wxCommandEvent& event)
|
||||
{
|
||||
// Forget all potential changes to PadMapping by loading the last saved settings
|
||||
g_Config.Load();
|
||||
|
||||
Close(); // Call OnClose()
|
||||
}
|
||||
}
|
||||
@ -485,7 +487,13 @@ void ConfigBox::ChangeSettings( wxCommandEvent& event )
|
||||
UpdateGUI(notebookpage);
|
||||
}
|
||||
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:
|
||||
DoChangeJoystick();
|
||||
break;
|
||||
@ -555,17 +563,17 @@ void ConfigBox::UpdateGUI(int _notebookpage)
|
||||
m_CBShowAdvanced[_notebookpage]->SetValue(g_Config.bShowAdvanced);
|
||||
m_CBCheckFocus[_notebookpage]->SetValue(g_Config.bCheckFocus);
|
||||
m_AdvancedMapFilter[_notebookpage]->SetValue(g_Config.bNoTriggerFilter);
|
||||
m_RStrength[_notebookpage]->SetSelection(g_Config.RumbleStrength);
|
||||
#ifdef RERECORDING
|
||||
m_CheckRecording[_notebookpage]->SetValue(g_Config.bRecording);
|
||||
m_CheckPlayback[_notebookpage]->SetValue(g_Config.bPlayback);
|
||||
#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
|
||||
#ifdef _WIN32
|
||||
// Disabled pages
|
||||
bool Enabled = PadMapping[_notebookpage].enabled == 1 ? true : false;
|
||||
|
||||
// Enable or disable all buttons
|
||||
for(int i = IDB_ANALOG_MAIN_X; i <= IDB_BUTTONHALFPRESS; i++)
|
||||
m_Controller[_notebookpage]->FindItem(i)->Enable(Enabled);
|
||||
@ -680,11 +688,20 @@ void ConfigBox::CreateGUIControls()
|
||||
wxArrayString wxAS_TriggerType;
|
||||
wxAS_TriggerType.Add(wxString::FromAscii(TriggerType[InputCommon::CTL_TRIGGER_SDL]));
|
||||
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;
|
||||
for(int x = 1; x <= 100; x++)
|
||||
{
|
||||
@ -692,7 +709,6 @@ void ConfigBox::CreateGUIControls()
|
||||
arrayStringFor_Deadzone.Add(wxString::FromAscii(buffer));
|
||||
}
|
||||
|
||||
|
||||
// Populate all four pages
|
||||
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_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
|
||||
m_ControlType[i]->SetToolTip(wxT(
|
||||
"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_gGenSettings[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
|
||||
|
@ -112,16 +112,21 @@ class ConfigBox : public wxDialog
|
||||
wxStaticBoxSizer *m_gGenSettings[4];
|
||||
|
||||
wxStaticBoxSizer *m_gGenSettingsID[4];
|
||||
wxGridBagSizer * m_gGBGenSettings[4];
|
||||
wxGridBagSizer *m_gGBGenSettings[4];
|
||||
wxCheckBox *m_CBSaveByID[4], *m_CBShowAdvanced[4];
|
||||
wxStaticText *m_TSControltype[4], *m_TSTriggerType[4];
|
||||
|
||||
wxStaticBoxSizer *m_gStatusIn[4], *m_gStatusInSettings[4], *m_gStatusAdvancedSettings[4]; // Advanced settings
|
||||
wxBoxSizer *m_gStatusInSettingsH[4];
|
||||
wxGridBagSizer * m_GBAdvancedMainStick[4];
|
||||
wxGridBagSizer *m_GBAdvancedMainStick[4];
|
||||
wxStaticText *m_TStatusIn[4], *m_TStatusOut[4], *m_STDiagonal[4];
|
||||
wxComboBox *m_CoBDiagonal[4]; wxCheckBox *m_CBS_to_C[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
|
||||
wxStaticText *m_TStatusTriggers[4];
|
||||
@ -218,6 +223,8 @@ class ConfigBox : public wxDialog
|
||||
IDG_CONTROLLERTYPE, IDC_CONTROLTYPE, IDC_TRIGGERTYPE, // Controller type
|
||||
|
||||
IDC_SAVEBYID, IDC_SHOWADVANCED, // Settings
|
||||
|
||||
IDC_ENABLERUMBLE, IDC_RUMBLESTRENGTH, IDT_RUMBLESTRENGTH, // Rumble
|
||||
|
||||
ID_INSTATUS1, ID_INSTATUS2, ID_INSTATUS3, ID_INSTATUS4, // Advanced status
|
||||
ID_STATUSBMP1, ID_STATUSBMP2, ID_STATUSBMP3, ID_STATUSBMP4,
|
||||
|
@ -80,11 +80,12 @@ void ConfigBox::UpdateGUIButtonMapping(int controller)
|
||||
m_CoBDiagonal[controller]->SetValue(wxString::FromAscii(PadMapping[controller].SDiagonal.c_str()));
|
||||
m_CBS_to_C[controller]->SetValue(PadMapping[controller].bSquareToCircle);
|
||||
m_AdvancedMapFilter[controller]->SetValue(g_Config.bNoTriggerFilter);
|
||||
// Update Rumble checkbox
|
||||
m_Rumble[controller]->SetValue(PadMapping[controller].rumble);
|
||||
#ifdef RERECORDING
|
||||
m_CheckRecording[controller]->SetValue(g_Config.bRecording);
|
||||
m_CheckPlayback[controller]->SetValue(g_Config.bPlayback);
|
||||
#endif
|
||||
//LogMsg("m_TriggerType[%i] = %i\n", controller, PadMapping[controller].triggertype);
|
||||
|
||||
// Update D-Pad
|
||||
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();
|
||||
}
|
||||
|
||||
// Replace "-1" with "" in the GUI controls
|
||||
//if(ControlsCreated) ToBlank();
|
||||
}
|
||||
|
||||
/* Populate the PadMapping array with the dialog items settings (for example
|
||||
|
@ -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
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef USE_RUMBLE_DINPUT_HACK
|
||||
LPDIRECTINPUT8 g_pDI = NULL;
|
||||
LPDIRECTINPUTDEVICE8 g_pDevice = NULL;
|
||||
LPDIRECTINPUTEFFECT g_pEffect = NULL;
|
||||
|
||||
DWORD g_dwNumForceFeedbackAxis = 0;
|
||||
INT g_nXForce = 0;
|
||||
INT g_nYForce = 0;
|
||||
struct RUMBLE // GC Pad rumble DIDevice
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 g_pDevice; // 4 pads objects
|
||||
LPDIRECTINPUTEFFECT g_pEffect;
|
||||
DWORD g_dwNumForceFeedbackAxis;
|
||||
DIEFFECT eff;
|
||||
};
|
||||
|
||||
#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 EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext);
|
||||
HRESULT SetDeviceForcesXY();
|
||||
#endif
|
||||
void SetDeviceForcesXY(int pad, int nXYForce);
|
||||
|
||||
LPDIRECTINPUT8 g_Rumble; // DInput Rumble object
|
||||
RUMBLE pRumble[4]; // 4 GC Rumble Pads
|
||||
extern InputCommon::CONTROLLER_MAPPING PadMapping[4];
|
||||
|
||||
#elif defined(__linux__)
|
||||
#include <sys/types.h>
|
||||
@ -74,101 +71,36 @@ bool g_rumbleEnable = FALSE;
|
||||
struct ff_effect effect;
|
||||
bool CanRumble = false;
|
||||
#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
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus)
|
||||
|
||||
void Pad_Use_Rumble(u8 _numPAD)//, SPADStatus* _pPADStatus)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#ifdef USE_RUMBLE_DINPUT_HACK
|
||||
|
||||
// Enable or disable rumble
|
||||
if (PadState[_numPAD].halfpress)
|
||||
if (!g_pDI)
|
||||
if (FAILED(InitDirectInput(m_hWnd)))
|
||||
{
|
||||
MessageBox(NULL, SDL_GetError(), "Could not initialize DirectInput!", MB_ICONERROR);
|
||||
g_rumbleEnable = FALSE;
|
||||
//return;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_rumbleEnable = TRUE;
|
||||
if (PadMapping[_numPAD].rumble) {
|
||||
if (!g_Rumble) {
|
||||
|
||||
HWND rumble_hWnd = GetParent(m_hWnd);
|
||||
HWND TopLevel = GetParent(rumble_hWnd);
|
||||
|
||||
// Support both rendering to main window and not.
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
if (g_rumbleEnable)
|
||||
{
|
||||
g_pDevice->Acquire();
|
||||
|
||||
if (g_pEffect) g_pEffect->Start(1, 0);
|
||||
}
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
if (!fd)
|
||||
{
|
||||
@ -204,191 +136,257 @@ void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus)
|
||||
#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
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Rumble stuff :D!
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
//
|
||||
#ifdef USE_RUMBLE_DINPUT_HACK
|
||||
HRESULT InitDirectInput( HWND hDlg )
|
||||
|
||||
HRESULT InitRumble(HWND hWnd)
|
||||
{
|
||||
DIPROPDWORD dipdw;
|
||||
HRESULT hr;
|
||||
DIPROPDWORD dipdw;
|
||||
HRESULT hr;
|
||||
|
||||
// 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)))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
// 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_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;
|
||||
}
|
||||
// Look for a device we can use
|
||||
if (FAILED(hr = g_Rumble->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;
|
||||
}
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
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.
|
||||
|
||||
// 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;
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = FALSE;
|
||||
|
||||
// Set the cooperative level to let DInput know how this device should
|
||||
// interact with the system and with other DInput applications.
|
||||
// Exclusive access is required in order to perform force feedback.
|
||||
//if (FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
|
||||
// if Force Feedback doesn't seem to work...
|
||||
if (FAILED(pRumble[i].g_pDevice->EnumObjects(EnumAxesCallback,
|
||||
(void*)&pRumble[i].g_dwNumForceFeedbackAxis, DIDFT_AXIS))
|
||||
|| FAILED(pRumble[i].g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph)))
|
||||
{
|
||||
PanicAlert("Device %d doesn't seem to work ! \nRumble for device %d is now Disabled !", i+1);
|
||||
|
||||
if (FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
PadMapping[i].rumble = false; // Disable Rumble for this pad
|
||||
|
||||
// Since we will be playing force feedback effects, we should disable the
|
||||
// auto-centering spring.
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = FALSE;
|
||||
continue; // Next pad
|
||||
}
|
||||
|
||||
if (FAILED(hr = g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph)))
|
||||
return hr;
|
||||
if (pRumble[i].g_dwNumForceFeedbackAxis > 2)
|
||||
pRumble[i].g_dwNumForceFeedbackAxis = 2;
|
||||
|
||||
// Enumerate and count the axes of the joystick
|
||||
if (FAILED(hr = g_pDevice->EnumObjects(EnumAxesCallback, (VOID*)&g_dwNumForceFeedbackAxis, DIDFT_AXIS)))
|
||||
return hr;
|
||||
DWORD _rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y};
|
||||
long rglDirection[2] = {0, 0};
|
||||
DICONSTANTFORCE cf = {0};
|
||||
|
||||
// This simple sample only supports one or two axis joysticks
|
||||
if (g_dwNumForceFeedbackAxis > 2)
|
||||
g_dwNumForceFeedbackAxis = 2;
|
||||
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;
|
||||
|
||||
// This application needs only one effect: Applying raw forces.
|
||||
DWORD rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y};
|
||||
LONG rglDirection[2] = {0, 0};
|
||||
DICONSTANTFORCE cf = {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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Create the prepared effect
|
||||
if (FAILED(hr = g_pDevice->CreateEffect(GUID_ConstantForce, &eff, &g_pEffect, NULL)))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
void SetDeviceForcesXY(int npad, int nXYForce)
|
||||
{
|
||||
// Security check
|
||||
if (pRumble[npad].g_pDevice == NULL)
|
||||
return;
|
||||
|
||||
if (NULL == g_pEffect)
|
||||
return E_FAIL;
|
||||
// If nXYForce is null, there's no point to create the effect
|
||||
// Just stop the force feedback
|
||||
if (nXYForce == 0) {
|
||||
pRumble[npad].g_pEffect->Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
long rglDirection[2] = {0};
|
||||
DICONSTANTFORCE cf;
|
||||
|
||||
return S_OK;
|
||||
// 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)
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 pDevice;
|
||||
DIPROPDWORD dipdw;
|
||||
HRESULT hr;
|
||||
|
||||
int JoystickID;
|
||||
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
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;
|
||||
|
||||
//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);
|
||||
|
||||
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)
|
||||
{
|
||||
DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; // Enum Rumble Axis
|
||||
if ((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0)
|
||||
(*pdwNumForceFeedbackAxis)++;
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
VOID FreeDirectInput()
|
||||
{
|
||||
// Unacquire the device one last time just in case
|
||||
// the app tried to exit while the device is still acquired.
|
||||
if (g_pDevice)
|
||||
g_pDevice->Unacquire();
|
||||
|
||||
// Release any DirectInput objects.
|
||||
SAFE_RELEASE(g_pEffect);
|
||||
SAFE_RELEASE(g_pDevice);
|
||||
SAFE_RELEASE(g_pDI);
|
||||
for (int i=0; i<4; i++) // Free all pads
|
||||
{
|
||||
if (pRumble[i].g_pDevice) {
|
||||
pRumble[i].g_pEffect->Stop();
|
||||
pRumble[i].g_pDevice->Unacquire();
|
||||
}
|
||||
|
||||
SAFE_RELEASE(pRumble[i].g_pEffect);
|
||||
SAFE_RELEASE(pRumble[i].g_pDevice);
|
||||
}
|
||||
|
||||
SAFE_RELEASE(g_Rumble); // Rumble object
|
||||
}
|
||||
|
||||
BOOL CALLBACK EnumFFDevicesCallback( const DIDEVICEINSTANCE* pInst, VOID* pContext )
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 pDevice;
|
||||
HRESULT hr;
|
||||
|
||||
// Obtain an interface to the enumerated force feedback device.
|
||||
hr = g_pDI->CreateDevice(pInst->guidInstance, &pDevice, NULL);
|
||||
|
||||
// If it failed, then we can't use this device for some bizarre reason.
|
||||
// (Maybe the user unplugged it while we were in the middle of enumerating it.) So continue enumerating
|
||||
if (FAILED(hr))
|
||||
return DIENUM_CONTINUE;
|
||||
|
||||
// We successfully created an IDirectInputDevice8. So stop looking for another one.
|
||||
g_pDevice = pDevice;
|
||||
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext)
|
||||
{
|
||||
DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext;
|
||||
if ((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0)
|
||||
(*pdwNumForceFeedbackAxis)++;
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
HRESULT SetDeviceForcesXY()
|
||||
{
|
||||
// Modifying an effect is basically the same as creating a new one, except you need only specify the parameters you are modifying
|
||||
LONG rglDirection[2] = { 0, 0 };
|
||||
|
||||
DICONSTANTFORCE cf;
|
||||
|
||||
if (g_dwNumForceFeedbackAxis == 1)
|
||||
{
|
||||
// If only one force feedback axis, then apply only one direction and keep the direction at zero
|
||||
cf.lMagnitude = g_nXForce;
|
||||
rglDirection[0] = 0;
|
||||
}
|
||||
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;
|
||||
ZeroMemory(&eff, sizeof(eff));
|
||||
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.
|
||||
return g_pEffect->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
// Author: Falcon4ever (nJoy@falcon4ever.com)
|
||||
// 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
|
||||
window correctly. So currently in Linux you have to have advanced controls enabled when
|
||||
you open the window to see them.
|
||||
// TODO : we should not need a Hack in the first place :/
|
||||
|
||||
////////////////////////*/
|
||||
|
||||
@ -80,7 +81,6 @@
|
||||
// Variables
|
||||
// ¯¯¯¯¯¯¯¯¯
|
||||
|
||||
// Rumble in windows
|
||||
#define _EXCLUDE_MAIN_ // Avoid certain declarations in nJoy.h
|
||||
FILE *pFile;
|
||||
HINSTANCE nJoy_hInst = NULL;
|
||||
@ -95,14 +95,11 @@ int NumPads = 0, NumGoodPads = 0, LastPad = 0;
|
||||
SPADInitialize *g_PADInitialize = NULL;
|
||||
PLUGIN_GLOBALS* globals = NULL;
|
||||
|
||||
// Rumble
|
||||
#ifdef _WIN32
|
||||
|
||||
#elif defined(__linux__)
|
||||
// Rumble
|
||||
#if defined(__linux__)
|
||||
extern int fd;
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// wxWidgets
|
||||
// ¯¯¯¯¯¯¯¯¯
|
||||
@ -249,15 +246,15 @@ void Initialize(void *init)
|
||||
INFO_LOG(CONSOLE, "Initialize: %i\n", SDL_WasInit(0));
|
||||
g_PADInitialize = (SPADInitialize*)init;
|
||||
g_EmulatorRunning = true;
|
||||
|
||||
#ifdef _WIN32
|
||||
m_hWnd = (HWND)g_PADInitialize->hWnd;
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
DEBUG_INIT();
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
m_hWnd = (HWND)g_PADInitialize->hWnd;
|
||||
#endif
|
||||
|
||||
// Populate joyinfo for all attached devices if the configuration window is not already open
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
if(!m_frame)
|
||||
@ -327,9 +324,7 @@ void Shutdown()
|
||||
g_PADInitialize = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef USE_RUMBLE_DINPUT_HACK
|
||||
FreeDirectInput();
|
||||
#endif
|
||||
FreeDirectInput();
|
||||
#elif defined(__linux__)
|
||||
close(fd);
|
||||
#endif
|
||||
@ -415,6 +410,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ----------------------
|
||||
|
||||
// Clear pad status
|
||||
@ -426,6 +422,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
|
||||
|
||||
// Get type
|
||||
int TriggerType = PadMapping[_numPAD].triggertype;
|
||||
int TriggerValue = PadState[_numPAD].halfpress ? 100 : 255;
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// The analog controls
|
||||
@ -440,7 +437,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
|
||||
int TriggerRight = PadState[_numPAD].axis[InputCommon::CTL_R_SHOULDER];
|
||||
|
||||
// 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);
|
||||
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);
|
||||
|
||||
// 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_R_SHOULDER] >= 1000) TriggerRight = InputCommon::Pad_Convert(TriggerRight);
|
||||
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);
|
||||
}
|
||||
|
||||
// Set Deadzones (perhaps out of function?)
|
||||
int deadzone = (int)(((float)(128.00/100.00)) * (float)(PadMapping[_numPAD].deadzone + 1));
|
||||
int deadzone2 = (int)(((float)(-128.00/100.00)) * (float)(PadMapping[_numPAD].deadzone + 1));
|
||||
// Set Deadzone
|
||||
float deadzone = (128.00 * (float)(PadMapping[_numPAD].deadzone + 1.00)) / 100.00;
|
||||
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
|
||||
if ((main_stick_x < deadzone2) || (main_stick_x > deadzone)) _pPADStatus->stickX = main_stick_x;
|
||||
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;
|
||||
if ((sub_stick_y < deadzone2) || (sub_stick_y > deadzone)) _pPADStatus->substickY = sub_stick_y;
|
||||
|
||||
if (distance_main > deadzone)
|
||||
{
|
||||
_pPADStatus->stickX = main_stick_x;
|
||||
_pPADStatus->stickY = main_stick_y;
|
||||
}
|
||||
if (distance_sub > deadzone)
|
||||
{
|
||||
_pPADStatus->substickX = sub_stick_x;
|
||||
_pPADStatus->substickY = sub_stick_y;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// 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
|
||||
if (PadState[_numPAD].buttons[InputCommon::CTL_L_SHOULDER])
|
||||
{
|
||||
_pPADStatus->button |= PAD_TRIGGER_L;
|
||||
if (!PadState[_numPAD].halfpress)
|
||||
_pPADStatus->button |= PAD_TRIGGER_L;
|
||||
_pPADStatus->triggerLeft = TriggerValue;
|
||||
}
|
||||
// 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;
|
||||
|
||||
// Check if the digital R button is pressed
|
||||
if (PadState[_numPAD].buttons[InputCommon::CTL_R_SHOULDER])
|
||||
{
|
||||
_pPADStatus->button |= PAD_TRIGGER_R;
|
||||
if (!PadState[_numPAD].halfpress)
|
||||
_pPADStatus->button |= PAD_TRIGGER_R;
|
||||
_pPADStatus->triggerRight = TriggerValue;
|
||||
}
|
||||
// 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;
|
||||
|
||||
// Update the buttons in analog mode to
|
||||
if(TriggerLeft == 0xff) _pPADStatus->button |= PAD_TRIGGER_L;
|
||||
if(TriggerRight == 0xff) _pPADStatus->button |= PAD_TRIGGER_R;
|
||||
// Update the buttons in analog mode too
|
||||
if (TriggerLeft > 0xf0) _pPADStatus->button |= PAD_TRIGGER_L;
|
||||
if (TriggerRight > 0xf0) _pPADStatus->button |= PAD_TRIGGER_R;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
@ -548,9 +552,6 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
|
||||
// Update error code
|
||||
_pPADStatus->err = PAD_ERR_NONE;
|
||||
|
||||
// Use rumble
|
||||
Pad_Use_Rumble(_numPAD, _pPADStatus);
|
||||
|
||||
// -------------------------------------------
|
||||
// Rerecording
|
||||
// ----------------------
|
||||
|
@ -33,15 +33,6 @@
|
||||
#ifndef __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
|
||||
// ¯¯¯¯¯¯¯¯¯¯
|
||||
@ -71,13 +62,12 @@
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#ifdef USE_RUMBLE_DINPUT_HACK
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
#pragma comment(lib, "dinput8.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
#include <dinput.h>
|
||||
VOID FreeDirectInput(); // Needed in both nJoy.cpp and Rumble.cpp
|
||||
#endif
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
#pragma comment(lib, "dinput8.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
#include <dinput.h>
|
||||
void FreeDirectInput(); // Needed in both nJoy.cpp and Rumble.cpp
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -142,11 +132,10 @@ void DEBUG_INIT();
|
||||
void DEBUG_QUIT();
|
||||
bool IsFocus();
|
||||
bool ReloadDLL();
|
||||
#ifdef _WIN32
|
||||
HRESULT InitRumble(HWND hWnd);
|
||||
#endif
|
||||
|
||||
void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus); // Rumble
|
||||
|
||||
//void SaveConfig();
|
||||
//void LoadConfig();
|
||||
////////////////////////////////
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user