diff --git a/Source/Plugins/Plugin_PadSimple/Plugin_PadSimple.vcproj b/Source/Plugins/Plugin_PadSimple/Plugin_PadSimple.vcproj index 8e3e8453ef..3bf74a252b 100644 --- a/Source/Plugins/Plugin_PadSimple/Plugin_PadSimple.vcproj +++ b/Source/Plugins/Plugin_PadSimple/Plugin_PadSimple.vcproj @@ -590,6 +590,7 @@ LinkIncremental="1" SuppressStartupBanner="true" GenerateManifest="false" + GenerateDebugInformation="true" ProgramDatabaseFile="$(TargetDir)$(TargetName).pdb" RandomizedBaseAddress="1" DataExecutionPrevention="0" diff --git a/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.cpp b/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.cpp index fd55019652..b2b6211462 100644 --- a/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.cpp @@ -30,11 +30,17 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) EVT_CLOSE(ConfigDialog::OnClose) EVT_BUTTON(ID_CLOSE,ConfigDialog::OnCloseClick) EVT_BUTTON(ID_PAD_ABOUT,ConfigDialog::DllAbout) + EVT_CHECKBOX(ID_ATTACHED,ConfigDialog::ControllerSettingsChanged) EVT_CHECKBOX(ID_X360PAD,ConfigDialog::ControllerSettingsChanged) EVT_CHOICE(ID_X360PAD_CHOICE,ConfigDialog::ControllerSettingsChanged) EVT_CHECKBOX(ID_RUMBLE,ConfigDialog::ControllerSettingsChanged) EVT_CHECKBOX(ID_DISABLE,ConfigDialog::ControllerSettingsChanged) + //Recording + EVT_CHECKBOX(ID_RECORDING,ConfigDialog::ControllerSettingsChanged) + EVT_CHECKBOX(ID_PLAYBACK,ConfigDialog::ControllerSettingsChanged) + EVT_BUTTON(ID_SAVE_RECORDING,ConfigDialog::ControllerSettingsChanged) + EVT_BUTTON(CTL_A,ConfigDialog::OnButtonClick) EVT_BUTTON(CTL_B,ConfigDialog::OnButtonClick) EVT_BUTTON(CTL_X,ConfigDialog::OnButtonClick) @@ -145,18 +151,62 @@ void ConfigDialog::CreateGUIControls() #endif for(int i = 0; i < 4; i++) - { - sbDevice[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Controller Settings")); + { + // -------------------------------------------------------------------- + // Settings + // ----------------------------- + // Main horizontal container sDevice[i] = new wxBoxSizer(wxHORIZONTAL); + + sbDevice[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Controller Settings")); m_Attached[i] = new wxCheckBox(m_Controller[i], ID_ATTACHED, wxT("Controller attached"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Disable[i] = new wxCheckBox(m_Controller[i], ID_DISABLE, wxT("Disable when Dolphin is not in focus"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + sbDevice[i]->Add(m_Attached[i], 0, wxEXPAND|wxALL, 1); + sbDevice[i]->Add(m_Disable[i], 0, wxEXPAND|wxALL, 1); + #ifdef _WIN32 + m_SizeXInput[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("XInput Pad")); m_X360Pad[i] = new wxCheckBox(m_Controller[i], ID_X360PAD, wxT("Enable X360Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_X360PadC[i] = new wxChoice(m_Controller[i], ID_X360PAD_CHOICE, wxDefaultPosition, wxDefaultSize, arrayStringFor_X360Pad, 0, wxDefaultValidator); m_Rumble[i] = new wxCheckBox(m_Controller[i], ID_RUMBLE, wxT("Enable rumble"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + + m_SizeXInput[i]->Add(m_X360Pad[i], 0, wxEXPAND | wxALL, 1); + m_SizeXInput[i]->Add(m_X360PadC[i], 0, wxEXPAND | wxALL, 1); + m_SizeXInput[i]->Add(m_Rumble[i], 0, wxEXPAND | wxALL, 1); #endif - m_Disable[i] = new wxCheckBox(m_Controller[i], ID_DISABLE, wxT("Disable when Dolphin is not in focus"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + + m_SizeRecording[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Input Recording")); + m_CheckRecording[i] = new wxCheckBox(m_Controller[i], ID_RECORDING, wxT("Record input")); + m_CheckPlayback[i] = new wxCheckBox(m_Controller[i], ID_PLAYBACK, wxT("Play back input")); + m_BtnSaveRecording[i] = new wxButton(m_Controller[i], ID_SAVE_RECORDING, wxT("Save recording"), wxDefaultPosition, wxDefaultSize); + + // Tool tips + m_CheckRecording[i]->SetToolTip(wxT("Your recording will be saved to pad-record.bin in the Dolphin dir when you stop the game")); + m_CheckPlayback[i]->SetToolTip(wxT("Play back the pad-record.bin file from the Dolphin dir")); + m_BtnSaveRecording[i]->SetToolTip(wxT( + "This will save the current recording to pad-record.bin. Your recording will\n" + "also be automatically saved every 60 * 10 frames. And when you shut down the\n" + "game.")); + + m_SizeRecording[i]->Add(m_CheckRecording[i], 0, wxEXPAND | wxALL, 1); + m_SizeRecording[i]->Add(m_CheckPlayback[i], 0, wxEXPAND | wxALL, 1); + m_SizeRecording[i]->Add(m_BtnSaveRecording[i], 0, wxEXPAND | wxALL, 1); + + // Set values m_Attached[i]->SetValue(pad[i].bAttached); + m_Disable[i]->SetValue(pad[i].bDisable); + m_CheckRecording[i]->SetValue(pad[i].bRecording); + m_CheckPlayback[i]->SetValue(pad[i].bPlayback); + + // Only enable these options for pad 0 + m_CheckRecording[i]->Enable(false); m_CheckRecording[0]->Enable(true); + m_CheckPlayback[i]->Enable(false); m_CheckPlayback[0]->Enable(true); + m_BtnSaveRecording[i]->Enable(false); m_BtnSaveRecording[0]->Enable(true); + // Don't allow saving when we are not recording + m_BtnSaveRecording[i]->Enable(g_EmulatorRunning && pad[0].bRecording); + #ifdef _WIN32 + // Check if any XInput pad was found if (arrayStringFor_X360Pad.IsEmpty()) { m_X360Pad[i]->SetLabel(wxT("Enable X360Pad - No pad connected")); @@ -175,19 +225,21 @@ void ConfigDialog::CreateGUIControls() m_Rumble[i]->Enable(m_X360Pad[i]->IsChecked()); } #endif - m_Disable[i]->SetValue(pad[i].bDisable); - - sDevice[i]->Add(m_Attached[i], 0, wxEXPAND|wxALL, 1); - sDevice[i]->AddStretchSpacer(); + + // Sizers + sDevice[i]->Add(sbDevice[i], 0, wxEXPAND | wxALL, 1); + //sDevice[i]->AddStretchSpacer(); #ifdef _WIN32 - sDevice[i]->Add(m_X360Pad[i], 0, wxEXPAND|wxALL, 1); - sDevice[i]->Add(m_X360PadC[i], 0, wxEXPAND|wxALL, 1); - sDevice[i]->Add(m_Rumble[i], 0, wxEXPAND|wxALL, 1); - sDevice[i]->AddStretchSpacer(); + sDevice[i]->Add(m_SizeXInput[i], 0, wxEXPAND | wxALL, 1); + sDevice[i]->Add(m_SizeRecording[i], 0, wxEXPAND | wxALL, 1); + #endif - sDevice[i]->Add(m_Disable[i], 0, wxEXPAND|wxALL, 1); - sbDevice[i]->Add(sDevice[i], 0, wxEXPAND|wxALL, 1); + // ----------------------------------- + + // -------------------------------------------------------------------- + // Buttons + // ----------------------------- sButtons[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Buttons")); AddControl(m_Controller[i], &(m_ButtonA[i]), sButtons[i], "A: ", CTL_A, i); @@ -227,10 +279,13 @@ void ConfigDialog::CreateGUIControls() AddControl(m_Controller[i], &(m_CStickLeft[i]), sCStick[i], "Left: ", CTL_SUBLEFT, i); AddControl(m_Controller[i], &(m_CStickRight[i]), sCStick[i], "Right: ", CTL_SUBRIGHT, i); + // -------------------------------------------------------------------- + // Sizers + // ----------------------------- sPage[i] = new wxGridBagSizer(0, 0); sPage[i]->SetFlexibleDirection(wxBOTH); sPage[i]->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); - sPage[i]->Add(sbDevice[i], wxGBPosition(0, 0), wxGBSpan(1, 5), wxEXPAND|wxALL, 1); + sPage[i]->Add(sDevice[i], wxGBPosition(0, 0), wxGBSpan(1, 5), wxEXPAND|wxALL, 1); sPage[i]->Add(sButtons[i], wxGBPosition(1, 0), wxGBSpan(2, 1), wxALL, 1); sPage[i]->Add(sTriggers[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND|wxALL, 1); sPage[i]->Add(sModifiers[i], wxGBPosition(2, 1), wxGBSpan(1, 1), wxALL, 1); @@ -291,9 +346,15 @@ void ConfigDialog::ControllerSettingsChanged(wxCommandEvent& event) switch (event.GetId()) { + // General settings case ID_ATTACHED: pad[page].bAttached = m_Attached[page]->GetValue(); break; + case ID_DISABLE: + pad[page].bDisable = m_Disable[page]->GetValue(); + break; + + // XInput case ID_X360PAD: pad[page].bEnableXPad = event.IsChecked(); m_Rumble[page]->Enable(event.IsChecked()); @@ -305,9 +366,22 @@ void ConfigDialog::ControllerSettingsChanged(wxCommandEvent& event) case ID_RUMBLE: pad[page].bRumble = m_Rumble[page]->GetValue(); break; - case ID_DISABLE: - pad[page].bDisable = m_Disable[page]->GetValue(); + + case ID_RECORDING: + pad[page].bRecording = m_CheckRecording[page]->GetValue(); + // Turn off the other option + pad[page].bPlayback = false; m_CheckPlayback[page]->SetValue(false); break; + case ID_PLAYBACK: + pad[page].bPlayback = m_CheckPlayback[page]->GetValue(); + // Turn off the other option + pad[page].bRecording = false; m_CheckRecording[page]->SetValue(false); + break; + case ID_SAVE_RECORDING: + // Double check again that we are still running a game + if (g_EmulatorRunning) SaveRecord(); + break; + } } diff --git a/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.h b/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.h index 34d12ee34f..e5d58d74f6 100644 --- a/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.h +++ b/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.h @@ -50,7 +50,7 @@ class ConfigDialog : public wxDialog wxButton *m_About; wxButton *m_Close; - wxStaticBoxSizer *sbDevice[4]; + wxStaticBoxSizer *sbDevice[4], *m_SizeXInput[4], *m_SizeRecording[4]; wxBoxSizer *sDevice[4]; wxGridBagSizer *sPage[4]; wxStaticBoxSizer *sButtons[4]; @@ -67,6 +67,11 @@ class ConfigDialog : public wxDialog wxCheckBox *m_Disable[4]; wxCheckBox *m_Rumble[4]; + // Recording + wxCheckBox *m_CheckRecording[4]; + wxCheckBox *m_CheckPlayback[4]; + wxButton *m_BtnSaveRecording[4]; + wxButton *m_ButtonA[4]; wxButton *m_ButtonB[4]; wxButton *m_ButtonX[4]; @@ -99,11 +104,19 @@ class ConfigDialog : public wxDialog ID_CONTROLLERPAGE3, ID_CONTROLLERPAGE4, + // XInput pad ID_X360PAD_CHOICE, ID_X360PAD, + ID_RUMBLE, + + // Input recording + ID_RECORDING, + ID_PLAYBACK, + ID_SAVE_RECORDING, + + // General settings ID_ATTACHED, ID_DISABLE, - ID_RUMBLE, ID_PAD_ABOUT }; diff --git a/Source/Plugins/Plugin_PadSimple/Src/PadSimple.cpp b/Source/Plugins/Plugin_PadSimple/Src/PadSimple.cpp index ffdbb23ad3..74c07b6841 100644 --- a/Source/Plugins/Plugin_PadSimple/Src/PadSimple.cpp +++ b/Source/Plugins/Plugin_PadSimple/Src/PadSimple.cpp @@ -15,6 +15,10 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ + +////////////////////////////////////////////////////////////////////////////////////////// +// Include +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ #include #include @@ -22,43 +26,69 @@ #include "pluginspecs_pad.h" #include "PadSimple.h" #include "IniFile.h" - - +#include "ConsoleWindow.h" +#include "StringUtil.h" +#include "ChunkFile.h" #if defined(HAVE_WX) && HAVE_WX -#include "GUI/ConfigDlg.h" + #include "GUI/ConfigDlg.h" #endif #ifdef _WIN32 -#include "XInput.h" -#include "DirectInputBase.h" + #include "XInput.h" + #include "DirectInputBase.h" -DInput dinput; -//#elif defined(USE_SDL) && USE_SDL -//#include + DInput dinput; + //#elif defined(USE_SDL) && USE_SDL + //#include #elif defined(HAVE_X11) && HAVE_X11 -#include -#include -#include -#include + #include + #include + #include + #include -Display* GXdsp; -bool KeyStatus[NUMCONTROLS]; + Display* GXdsp; + bool KeyStatus[NUMCONTROLS]; #elif defined(HAVE_COCOA) && HAVE_COCOA -#include -bool KeyStatus[NUMCONTROLS]; + #include + bool KeyStatus[NUMCONTROLS]; #endif +//////////////////////////////// + +////////////////////////////////////////////////////////////////////////////////////////// +// Declarations +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ SPads pad[4]; HINSTANCE g_hInstance; SPADInitialize g_PADInitialize; +//////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////////////////// +// Input Recording +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ + +// Enable these to record or play back +//#define RECORD_REPLAY +//#define RECORD_STORE + +// Pre defined maxium storage limit #define RECORD_SIZE (1024 * 128) SPADStatus recordBuffer[RECORD_SIZE]; int count = 0; +bool g_EmulatorRunning = false; +//////////////////////////////// + + +// TODO: fix this dirty hack to stop missing symbols +void __Log(int log, const char *format, ...) {} +void __Logv(int log, int v, const char *format, ...) {} + //****************************************************************************** // Supporting functions @@ -66,46 +96,68 @@ int count = 0; void RecordInput(const SPADStatus& _rPADStatus) { - if (count >= RECORD_SIZE) - { - return; - } - + if (count >= RECORD_SIZE) return; recordBuffer[count++] = _rPADStatus; -} + // Logging + //u8 TmpData[sizeof(SPADStatus)]; + //memcpy(TmpData, &recordBuffer[count - 1], sizeof(SPADStatus)); + //Console::Print("RecordInput(%i): %s\n", count, ArrayToString(TmpData, sizeof(SPADStatus), 0, 30).c_str()); + + // Auto save every ten seconds + if (count % (60 * 10) == 0) SaveRecord(); +} const SPADStatus& PlayRecord() { - if (count >= RECORD_SIZE){return(recordBuffer[0]);} + // Logging + //Console::Print("PlayRecord(%i)\n", count); + if (count >= RECORD_SIZE) + { + // Todo: Make the recording size unlimited? + //PanicAlert("The recording reached its end"); + return(recordBuffer[0]); + } return(recordBuffer[count++]); } - void LoadRecord() { - FILE* pStream = fopen("c:\\pad-record.bin", "rb"); + FILE* pStream = fopen("pad-record.bin", "rb"); if (pStream != NULL) { fread(recordBuffer, 1, RECORD_SIZE * sizeof(SPADStatus), pStream); fclose(pStream); } -} + else + { + PanicAlert("SimplePad: Could not open pad-record.bin"); + } + //Console::Print("LoadRecord()"); +} void SaveRecord() { - FILE* pStream = fopen("c:\\pad-record.bin", "wb"); + // Open the file in a way that clears all old data + FILE* pStream = fopen("pad-record.bin", "wb"); if (pStream != NULL) { fwrite(recordBuffer, 1, RECORD_SIZE * sizeof(SPADStatus), pStream); fclose(pStream); } + else + { + PanicAlert("SimplePad: Could not save pad-record.bin"); + } + //PanicAlert("SaveRecord()"); + //Console::Print("SaveRecord()"); } + // Check if Dolphin is in focus bool IsFocus() { @@ -167,89 +219,6 @@ BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle #endif -//****************************************************************************** -// Plugin specification functions -//****************************************************************************** - - -void GetDllInfo(PLUGIN_INFO* _PluginInfo) -{ - _PluginInfo->Version = 0x0100; - _PluginInfo->Type = PLUGIN_TYPE_PAD; - -#ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (DebugFast)"); -#else -#ifndef _DEBUG - sprintf(_PluginInfo->Name, "Dolphin KB/X360pad"); -#else - sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (Debug)"); -#endif -#endif - -} - -void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals) { -} - -void DllConfig(HWND _hParent) -{ - LoadConfig(); -#ifdef _WIN32 - wxWindow win; - win.SetHWND(_hParent); - ConfigDialog frame(&win); - frame.ShowModal(); - win.SetHWND(0); -#elif defined(HAVE_WX) && HAVE_WX - ConfigDialog frame(NULL); - frame.ShowModal(); -#endif - SaveConfig(); -} - -void DllDebugger(HWND _hParent, bool Show) { -} - -void Initialize(void *init) -{ -#ifdef RECORD_REPLAY - LoadRecord(); -#endif - - g_PADInitialize = *(SPADInitialize*)init; -#ifdef _WIN32 - dinput.Init((HWND)g_PADInitialize.hWnd); -#elif defined(HAVE_X11) && HAVE_X11 - GXdsp = (Display*)g_PADInitialize.hWnd; -#elif defined(HAVE_COCOA) && HAVE_COCOA -#endif - - LoadConfig(); -} - -void DoState(unsigned char **ptr, int mode) { -} - -void Shutdown() -{ -#ifdef RECORD_STORE - SaveRecord(); -#endif -#ifdef _WIN32 - dinput.Free(); - // Kill xpad rumble - XINPUT_VIBRATION vib; - vib.wLeftMotorSpeed = 0; - vib.wRightMotorSpeed = 0; - for (int i = 0; i < 4; i++) - if (pad[i].bRumble) - XInputSetState(pad[i].XPadPlayer, &vib); -#endif - SaveConfig(); -} - - const float kDeadZone = 0.1f; // Implement circular deadzone @@ -283,6 +252,9 @@ void ScaleStickValues(unsigned char* outx, *outy = 0x80 + iy; } +//****************************************************************************** +// Input +//****************************************************************************** #ifdef _WIN32 void DInput_Read(int _numPAD, SPADStatus* _pPADStatus) @@ -334,6 +306,8 @@ void DInput_Read(int _numPAD, SPADStatus* _pPADStatus) if (dinput.diks[pad[_numPAD].keyForControl[CTL_DPADLEFT]] & 0xFF){_pPADStatus->button |= PAD_BUTTON_LEFT;} if (dinput.diks[pad[_numPAD].keyForControl[CTL_DPADRIGHT]]& 0xFF){_pPADStatus->button |= PAD_BUTTON_RIGHT;} if (dinput.diks[pad[_numPAD].keyForControl[CTL_START]] & 0xFF){_pPADStatus->button |= PAD_BUTTON_START;} + + _pPADStatus->MicButton = (dinput.diks[pad[_numPAD].keyForControl[CTL_MIC]] & 0xFF) ? true : false; } bool XInput_Read(int XPadPlayer, SPADStatus* _pPADStatus) @@ -381,6 +355,8 @@ bool XInput_Read(int XPadPlayer, SPADStatus* _pPADStatus) if (xpad.wButtons & XINPUT_GAMEPAD_DPAD_UP) {_pPADStatus->button |= PAD_BUTTON_UP;} if (xpad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {_pPADStatus->button |= PAD_BUTTON_DOWN;} + //_pPADStatus->MicButton = (xpad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? true : false; + return true; } else @@ -610,25 +586,124 @@ void cocoa_Read(int _numPAD, SPADStatus* _pPADStatus) } #endif + + + +//****************************************************************************** +// Plugin specification functions +//****************************************************************************** + + +void GetDllInfo(PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_PAD; + +#ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (DebugFast)"); +#else +#ifndef _DEBUG + sprintf(_PluginInfo->Name, "Dolphin KB/X360pad"); +#else + sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (Debug)"); +#endif +#endif + +} + +void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals) {} + +void DllConfig(HWND _hParent) +{ + LoadConfig(); +#ifdef _WIN32 + wxWindow win; + win.SetHWND(_hParent); + ConfigDialog frame(&win); + frame.ShowModal(); + win.SetHWND(0); +#elif defined(HAVE_WX) && HAVE_WX + ConfigDialog frame(NULL); + frame.ShowModal(); +#endif + SaveConfig(); +} + +void DllDebugger(HWND _hParent, bool Show) {} + +void Initialize(void *init) +{ + //Console::Open(70, 5000); + + // We are now running a game + g_EmulatorRunning = true; + + // Load configuration + LoadConfig(); + + // Load recorded input if we are to play it back, otherwise begin with a blank recording + if (pad[0].bPlayback) LoadRecord(); + + g_PADInitialize = *(SPADInitialize*)init; + + #ifdef _WIN32 + dinput.Init((HWND)g_PADInitialize.hWnd); + #elif defined(HAVE_X11) && HAVE_X11 + GXdsp = (Display*)g_PADInitialize.hWnd; + #elif defined(HAVE_COCOA) && HAVE_COCOA + + #endif +} + +void DoState(unsigned char **ptr, int mode) +{ + // Load or save the counter + PointerWrap p(ptr, mode); + p.Do(count); +} + +void Shutdown() +{ + //Console::Print("ShutDown()\n"); + + // Save recording + if (pad[0].bRecording) SaveRecord(); + // Reset the counter + count = 0; + // We have stopped the game + g_EmulatorRunning = false; + +#ifdef _WIN32 + dinput.Free(); + // Kill xpad rumble + XINPUT_VIBRATION vib; + vib.wLeftMotorSpeed = 0; + vib.wRightMotorSpeed = 0; + for (int i = 0; i < 4; i++) + if (pad[i].bRumble) + XInputSetState(pad[i].XPadPlayer, &vib); +#endif + SaveConfig(); +} + + // Set buttons status from wxWidgets in the main application // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void PAD_Input(u16 _Key, u8 _UpDown) { -} +void PAD_Input(u16 _Key, u8 _UpDown) {} void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) { // Check if all is okay - if ((_pPADStatus == NULL)) + if (_pPADStatus == NULL) return; + + // Play back input instead of accepting any user input + if (pad[0].bPlayback) { + *_pPADStatus = PlayRecord(); return; } -#ifdef RECORD_REPLAY - *_pPADStatus = PlayRecord(); - return; -#endif - const int base = 0x80; // Clear pad memset(_pPADStatus, 0, sizeof(SPADStatus)); @@ -639,15 +714,18 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) _pPADStatus->substickY = base; _pPADStatus->button |= PAD_USE_ORIGIN; #ifdef _WIN32 - // Just update pad on focus - if (pad[_numPAD].bDisable) - { - if (!IsFocus()) return; - } + // Only update pad on focus, don't do this when recording + if (pad[_numPAD].bDisable && !pad[0].bRecording && !IsFocus()) return; + // Dolphin doesn't really care about the pad error codes anyways... _pPADStatus->err = PAD_ERR_NONE; + + // Read XInput if (pad[_numPAD].bEnableXPad) XInput_Read(pad[_numPAD].XPadPlayer, _pPADStatus); + + // Read Direct Input DInput_Read(_numPAD, _pPADStatus); + #elif defined(HAVE_X11) && HAVE_X11 _pPADStatus->err = PAD_ERR_NONE; X11_Read(_numPAD, _pPADStatus); @@ -656,9 +734,8 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) cocoa_Read(_numPAD, _pPADStatus); #endif -#ifdef RECORD_STORE - RecordInput(*_pPADStatus); -#endif + // Record input + if (pad[0].bRecording) RecordInput(*_pPADStatus); } @@ -742,7 +819,8 @@ void LoadConfig() DIK_G, DIK_F, DIK_H, - DIK_LSHIFT + DIK_LSHIFT, //halfpress + DIK_M //Mic }; #elif defined(HAVE_X11) && HAVE_X11 const int defaultKeyForControl[NUMCONTROLS] = @@ -768,7 +846,7 @@ void LoadConfig() XK_f, XK_h, XK_Shift_L, //halfpress - XK_p + XK_p //Mic }; #elif defined(HAVE_COCOA) && HAVE_COCOA const int defaultKeyForControl[NUMCONTROLS] = @@ -794,7 +872,7 @@ void LoadConfig() 3, 4, 56, //halfpress - 35 + 35 //Mic }; #endif IniFile file; @@ -811,6 +889,9 @@ void LoadConfig() file.Get(SectionName, "Rumble", &pad[i].bRumble, true); file.Get(SectionName, "XPad#", &pad[i].XPadPlayer); + file.Get(SectionName, "Recording", &pad[i].bRecording, false); + file.Get(SectionName, "Playback", &pad[i].bPlayback, false); + for (int x = 0; x < NUMCONTROLS; x++) { file.Get(SectionName, controlNames[x], &pad[i].keyForControl[x], @@ -840,6 +921,9 @@ void SaveConfig() file.Set(SectionName, "DisableOnBackground", pad[i].bDisable); file.Set(SectionName, "Rumble", pad[i].bRumble); file.Set(SectionName, "XPad#", pad[i].XPadPlayer); + // Recording + file.Set(SectionName, "Recording", pad[i].bRecording); + file.Set(SectionName, "Playback", pad[i].bPlayback); for (int x = 0; x < NUMCONTROLS; x++) { diff --git a/Source/Plugins/Plugin_PadSimple/Src/PadSimple.h b/Source/Plugins/Plugin_PadSimple/Src/PadSimple.h index 53e82feb25..ee2b055659 100644 --- a/Source/Plugins/Plugin_PadSimple/Src/PadSimple.h +++ b/Source/Plugins/Plugin_PadSimple/Src/PadSimple.h @@ -73,19 +73,26 @@ static const char* controlNames[] = "Mic-button", }; -struct SPads { +struct SPads +{ bool bEnableXPad; // Use an XPad in addition to the keyboard? bool bAttached; // Pad is "attached" to the gamecube/wii bool bDisable; // Disabled when dolphin isn't in focus bool bRumble; // Rumble for xpad + bool bRecording; + bool bPlayback; int XPadPlayer; // Player# of the xpad unsigned int keyForControl[NUMCONTROLS];// Keyboard mapping }; extern SPads pad[]; +extern bool g_EmulatorRunning; void LoadConfig(); void SaveConfig(); bool IsFocus(); +// Input Recording +void SaveRecord(); + #endif diff --git a/Source/Plugins/Plugin_nJoy_SDL/Plugin_nJoy_SDL.vcproj b/Source/Plugins/Plugin_nJoy_SDL/Plugin_nJoy_SDL.vcproj index b20c24766c..94adefdb65 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Plugin_nJoy_SDL.vcproj +++ b/Source/Plugins/Plugin_nJoy_SDL/Plugin_nJoy_SDL.vcproj @@ -522,14 +522,6 @@ RelativePath=".\Src\Rumble.cpp" > - - - - GetMinSize().GetWidth() will not change @@ -70,8 +70,10 @@ void ConfigBox::PadGetStatus() int PhysicalDevice = PadMapping[notebookpage].ID; int TriggerType = PadMapping[notebookpage].triggertype; - // Get pad status - GetJoyState(notebookpage); + // Check that Dolphin is in focus, otherwise don't update the pad status + if (!g_Config.bCheckFocus && IsFocus()) + InputCommon::GetJoyState(PadState[notebookpage], PadMapping[notebookpage], notebookpage, joyinfo[PadMapping[notebookpage].ID].NumButtons); + ////////////////////////////////////// // Analog stick @@ -81,8 +83,8 @@ void ConfigBox::PadGetStatus() //int deadzone2 = (int)(((float)(-128.00/100.00)) * (float)(PadMapping[_numPAD].deadzone+1)); // Get original values - int main_x = PadState[notebookpage].axis[CTL_MAIN_X]; - int main_y = PadState[notebookpage].axis[CTL_MAIN_Y]; + int main_x = PadState[notebookpage].axis[InputCommon::CTL_MAIN_X]; + int main_y = PadState[notebookpage].axis[InputCommon::CTL_MAIN_Y]; //int sub_x = (PadState[_numPAD].axis[CTL_SUB_X]; //int sub_y = -(PadState[_numPAD].axis[CTL_SUB_Y]; @@ -90,7 +92,7 @@ void ConfigBox::PadGetStatus() int main_x_after = main_x, main_y_after = main_y; if(PadMapping[notebookpage].bSquareToCircle) { - std::vector main_xy = Pad_Square_to_Circle(main_x, main_y, notebookpage); + std::vector main_xy = InputCommon::Pad_Square_to_Circle(main_x, main_y, notebookpage, PadMapping[notebookpage]); main_x_after = main_xy.at(0); main_y_after = main_xy.at(1); } @@ -138,14 +140,14 @@ void ConfigBox::PadGetStatus() m_JoyShoulderR[notebookpage]->GetValue().ToLong(&Right); // Get the trigger values - int TriggerLeft = PadState[notebookpage].axis[CTL_L_SHOULDER]; - int TriggerRight = PadState[notebookpage].axis[CTL_R_SHOULDER]; + int TriggerLeft = PadState[notebookpage].axis[InputCommon::CTL_L_SHOULDER]; + int TriggerRight = PadState[notebookpage].axis[InputCommon::CTL_R_SHOULDER]; // Convert the triggers values - if (PadMapping[notebookpage].triggertype == CTL_TRIGGER_SDL) + if (PadMapping[notebookpage].triggertype == InputCommon::CTL_TRIGGER_SDL) { - TriggerLeft = Pad_Convert(TriggerLeft); - TriggerRight = Pad_Convert(TriggerRight); + TriggerLeft = InputCommon::Pad_Convert(TriggerLeft); + TriggerRight = InputCommon::Pad_Convert(TriggerRight); } // If we don't have any axis selected for the shoulder buttons @@ -153,8 +155,8 @@ void ConfigBox::PadGetStatus() if(Right < 1000) TriggerRight = 0; // Get the digital values - if(Left < 1000 && PadState[notebookpage].buttons[CTL_L_SHOULDER]) TriggerLeft = TriggerValue; - if(Right < 1000 && PadState[notebookpage].buttons[CTL_R_SHOULDER]) TriggerRight = TriggerValue; + if(Left < 1000 && PadState[notebookpage].buttons[InputCommon::CTL_L_SHOULDER]) TriggerLeft = TriggerValue; + if(Right < 1000 && PadState[notebookpage].buttons[InputCommon::CTL_R_SHOULDER]) TriggerRight = TriggerValue; m_TStatusTriggers[notebookpage]->SetLabel(wxString::Format( wxT("Left:%03i Right:%03i"), @@ -192,6 +194,10 @@ std::string ShowStatus(int VirtualController) int Hats = joyinfo[PhysicalDevice].NumHats; int Buttons = joyinfo[PhysicalDevice].NumButtons; + // Get version + //SDL_version Version; + //SDL_GetVersion(&Version); + // Update the internal values SDL_JoystickUpdate(); @@ -213,7 +219,7 @@ std::string ShowStatus(int VirtualController) } return StringFromFormat( - "PadMapping\n" + //"Version: %i.%i.%i\n" "Enabled: %i %i %i %i\n" "ID: %i %i %i %i\n" "Controllertype: %i %i %i %i\n" @@ -225,6 +231,7 @@ std::string ShowStatus(int VirtualController) "Hats: %s\n" "But: %s\n" "Device: Ax: %i Balls:%i Hats:%i But:%i", + //Version.major, Version.minor, Version.patch, PadMapping[0].enabled, PadMapping[1].enabled, PadMapping[2].enabled, PadMapping[3].enabled, PadMapping[0].ID, PadMapping[1].ID, PadMapping[2].ID, PadMapping[3].ID, PadMapping[0].controllertype, PadMapping[1].controllertype, PadMapping[2].controllertype, PadMapping[3].controllertype, @@ -233,7 +240,7 @@ std::string ShowStatus(int VirtualController) //PadState[PadMapping[0].ID].joy, PadState[PadMapping[1].ID].joy, PadState[PadMapping[2].ID].joy, PadState[PadMapping[3].ID].joy, #ifdef _WIN32 - XInput::IsConnected(0), XInput::GetXI(0, XI_TRIGGER_L), XInput::GetXI(0, XI_TRIGGER_R), + XInput::IsConnected(0), XInput::GetXI(0, InputCommon::XI_TRIGGER_L), XInput::GetXI(0, InputCommon::XI_TRIGGER_R), #endif StrAxes.c_str(), StrHats.c_str(), StrBut.c_str(), Axes, Balls, Hats, Buttons @@ -245,10 +252,12 @@ std::string ShowStatus(int VirtualController) void ConfigBox::Update() { // Show the current status - /* - m_pStatusBar->SetLabel(wxString::Format( - "%s", ShowStatus(notebookpage).c_str() - ));*/ + /**/ + #ifdef SHOW_PAD_STATUS + m_pStatusBar->SetLabel(wxString::Format( + "%s", ShowStatus(notebookpage).c_str() + )); + #endif //LogMsg("Abc%s\n", ShowStatus(notebookpage).c_str()); @@ -261,6 +270,10 @@ void ConfigBox::Update() // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ void ConfigBox::CreateAdvancedControls(int i) { + m_TStatusIn[i] = new wxStaticText(m_Controller[i], IDT_STATUS_IN, wxT("In")); + m_TStatusOut[i] = new wxStaticText(m_Controller[i], IDT_STATUS_OUT, wxT("Out")); + m_gStatusIn[i] = new wxStaticBoxSizer( wxHORIZONTAL, m_Controller[i], wxT("Main-stick (In) (Out)")); + m_pInStatus[i] = new wxPanel(m_Controller[i], ID_INSTATUS1 + i, wxDefaultPosition, wxDefaultSize); m_bmpSquare[i] = new wxStaticBitmap(m_pInStatus[i], ID_STATUSBMP1 + i, CreateBitmap(), //wxPoint(4, 15), wxSize(70,70)); diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp index b1a2d48e53..076c908267 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp @@ -39,7 +39,7 @@ #include "../nJoy.h" #include "Images/controller.xpm" -extern bool emulator_running; +extern bool g_EmulatorRunning; // D-Pad type static const char* DPadType[] = @@ -74,7 +74,7 @@ BEGIN_EVENT_TABLE(ConfigBox,wxDialog) // Other settings EVT_CHECKBOX(IDC_SAVEBYID, ConfigBox::ChangeSettings) EVT_CHECKBOX(IDC_SHOWADVANCED, ConfigBox::ChangeSettings) - EVT_CHECKBOX(IDC_CHECKFOCUS, ConfigBox::ChangeSettings) + EVT_CHECKBOX(IDCB_CHECKFOCUS, ConfigBox::ChangeSettings) EVT_COMBOBOX(IDCB_MAINSTICK_DIAGONAL, ConfigBox::ChangeSettings) EVT_COMBOBOX(IDC_CONTROLTYPE, ConfigBox::ChangeSettings) EVT_COMBOBOX(IDC_TRIGGERTYPE, ConfigBox::ChangeSettings) @@ -83,6 +83,7 @@ BEGIN_EVENT_TABLE(ConfigBox,wxDialog) // Advanced settings EVT_COMBOBOX(IDCB_MAINSTICK_DIAGONAL, ConfigBox::ChangeSettings) EVT_CHECKBOX(IDCB_MAINSTICK_S_TO_C, ConfigBox::ChangeSettings) + EVT_CHECKBOX(IDCB_FILTER_SETTINGS, ConfigBox::ChangeSettings) EVT_BUTTON(IDB_SHOULDER_L, ConfigBox::GetButtons) EVT_BUTTON(IDB_SHOULDER_R, ConfigBox::GetButtons) @@ -161,7 +162,7 @@ void ConfigBox::OnKeyDown(wxKeyEvent& event) void ConfigBox::OnClose(wxCloseEvent& /*event*/) { EndModal(0); - if(!emulator_running) Shutdown(); // Close pads, unless we are running a game + if(!g_EmulatorRunning) Shutdown(); // Close pads, unless we are running a game } // Call about dialog @@ -291,7 +292,8 @@ void ConfigBox::OnSaveById() // Change Joystick // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ /* Function: When changing the joystick we save and load the settings and update the PadMapping - and PadState array */ + and PadState array. PadState[].joy is the gamepad handle that is used to access the pad throughout + the plugin. Joyinfo[].joy is only used the first time the pads are checked. */ void ConfigBox::DoChangeJoystick() { // Close the current pad, unless it's used by another slot @@ -425,16 +427,34 @@ void ConfigBox::ChangeSettings( wxCommandEvent& event ) } SizeWindow(); break; - case IDC_CHECKFOCUS: + // Advanced settings + case IDCB_CHECKFOCUS: g_Config.bCheckFocus = m_CBCheckFocus[notebookpage]->IsChecked(); for(int i = 0; i < 4; i++) { m_CBCheckFocus[i]->SetValue(g_Config.bCheckFocus); } break; + case IDCB_FILTER_SETTINGS: + g_Config.bNoTriggerFilter = m_AdvancedMapFilter[notebookpage]->IsChecked(); + for(int i = 0; i < 4; i++) + { + m_AdvancedMapFilter[i]->SetValue(g_Config.bNoTriggerFilter); + } + break; + case IDC_CONTROLTYPE: + if(!g_Config.bSaveByID) + { + PadMapping[notebookpage].controllertype = m_ControlType[notebookpage]->GetSelection(); + UpdateGUI(notebookpage); + } case IDC_TRIGGERTYPE: - //UpdateGUI(notebookpage); + if(!g_Config.bSaveByID) + { + PadMapping[notebookpage].triggertype = m_TriggerType[notebookpage]->GetSelection(); + UpdateGUI(notebookpage); + } break; case IDC_JOYNAME: @@ -472,10 +492,10 @@ void ConfigBox::UpdateGUI(int _notebookpage) } // Update the GUI from PadMapping[] - UpdateGUIKeys(_notebookpage); + UpdateGUIButtonMapping(_notebookpage); // Collect status - bool Hat = (PadMapping[_notebookpage].controllertype == CTL_DPAD_HAT); + bool Hat = (PadMapping[_notebookpage].controllertype == InputCommon::CTL_DPAD_HAT); long Left, Right; m_JoyShoulderL[_notebookpage]->GetValue().ToLong(&Left); m_JoyShoulderR[_notebookpage]->GetValue().ToLong(&Right); @@ -505,6 +525,7 @@ void ConfigBox::UpdateGUI(int _notebookpage) m_CBSaveByID[_notebookpage]->SetValue(g_Config.bSaveByID); m_CBShowAdvanced[_notebookpage]->SetValue(g_Config.bShowAdvanced); m_CBCheckFocus[_notebookpage]->SetValue(g_Config.bCheckFocus); + m_AdvancedMapFilter[_notebookpage]->SetValue(g_Config.bNoTriggerFilter); LogMsg("Update: %i\n", g_Config.bSaveByID); @@ -520,7 +541,8 @@ void ConfigBox::UpdateGUI(int _notebookpage) m_Controller[_notebookpage]->FindItem(IDC_CONTROLTYPE)->Enable(Enabled); m_Controller[_notebookpage]->FindItem(IDC_TRIGGERTYPE)->Enable(Enabled && XInput); m_Controller[_notebookpage]->FindItem(IDCB_MAINSTICK_DIAGONAL)->Enable(Enabled); - m_Controller[_notebookpage]->FindItem(IDCB_MAINSTICK_S_TO_C)->Enable(Enabled); + m_Controller[_notebookpage]->FindItem(IDCB_MAINSTICK_S_TO_C)->Enable(Enabled); + m_Controller[_notebookpage]->FindItem(IDCB_FILTER_SETTINGS)->Enable(Enabled); #endif // Replace the harder to understand -1 with "" for the sake of user friendliness @@ -619,12 +641,12 @@ void ConfigBox::CreateGUIControls() // Populate the DPad type and Trigger type list // ----------------------------- wxArrayString wxAS_DPadType; - wxAS_DPadType.Add(wxString::FromAscii(DPadType[CTL_DPAD_HAT])); - wxAS_DPadType.Add(wxString::FromAscii(DPadType[CTL_DPAD_CUSTOM])); + wxAS_DPadType.Add(wxString::FromAscii(DPadType[InputCommon::CTL_DPAD_HAT])); + wxAS_DPadType.Add(wxString::FromAscii(DPadType[InputCommon::CTL_DPAD_CUSTOM])); wxArrayString wxAS_TriggerType; - wxAS_TriggerType.Add(wxString::FromAscii(TriggerType[CTL_TRIGGER_SDL])); - wxAS_TriggerType.Add(wxString::FromAscii(TriggerType[CTL_TRIGGER_XINPUT])); + wxAS_TriggerType.Add(wxString::FromAscii(TriggerType[InputCommon::CTL_TRIGGER_SDL])); + wxAS_TriggerType.Add(wxString::FromAscii(TriggerType[InputCommon::CTL_TRIGGER_XINPUT])); // -------------------------------------------------------------------- // Populate the deadzone list @@ -820,12 +842,10 @@ void ConfigBox::CreateGUIControls() m_gGenSettingsID[i] = new wxStaticBoxSizer( wxVERTICAL, m_Controller[i], wxT("Settings") ); m_CBSaveByID[i] = new wxCheckBox(m_Controller[i], IDC_SAVEBYID, wxT("Save by ID"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_CBShowAdvanced[i] = new wxCheckBox(m_Controller[i], IDC_SHOWADVANCED, wxT("Show advanced settings"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_CBCheckFocus[i] = new wxCheckBox(m_Controller[i], IDC_CHECKFOCUS, wxT("Allow out of focus input"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); // Populate general settings 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_CBCheckFocus[i], 0, wxEXPAND | wxALL, 3); // Create tooltips m_ControlType[i]->SetToolTip(wxT( @@ -840,8 +860,6 @@ void ConfigBox::CreateGUIControls() "\nto save your settings if you have multiple controllers.") , i+1 )); - m_CBCheckFocus[i]->SetToolTip(wxT( - "Allow gamepad input even when Dolphin is not in focus. Out of focus keyboard input is never allowed.")); // Populate settings m_sSettings[i] = new wxBoxSizer ( wxHORIZONTAL ); @@ -857,17 +875,13 @@ void ConfigBox::CreateGUIControls() // Advanced settings // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ - // Populate input status - /**/ + // Input status controls // Input status text - m_TStatusIn[i] = new wxStaticText(m_Controller[i], IDT_STATUS_IN, wxT("In")); - m_TStatusOut[i] = new wxStaticText(m_Controller[i], IDT_STATUS_OUT, wxT("Out")); - - m_gStatusIn[i] = new wxStaticBoxSizer( wxHORIZONTAL, m_Controller[i], wxT("Main-stick (In) (Out)")); CreateAdvancedControls(i); - m_GBAdvancedMainStick[i] = new wxGridBagSizer(0, 0); + // Sizers + m_GBAdvancedMainStick[i] = new wxGridBagSizer(0, 0); m_GBAdvancedMainStick[i]->Add(m_pInStatus[i], wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0); m_GBAdvancedMainStick[i]->Add(m_pOutStatus[i], wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 5); m_GBAdvancedMainStick[i]->Add(m_TStatusIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0); @@ -911,6 +925,20 @@ void ConfigBox::CreateGUIControls() m_gStatusTriggers[i] = new wxStaticBoxSizer( wxVERTICAL, m_Controller[i], wxT("Trigger values")); m_TStatusTriggers[i] = new wxStaticText(m_Controller[i], IDT_TRIGGERS, wxT("Left: Right:")); m_gStatusTriggers[i]->Add(m_TStatusTriggers[i], 0, (wxALL), 4); + + m_gStatusAdvancedSettings[i] = new wxStaticBoxSizer( wxVERTICAL, m_Controller[i], wxT("Advanced settings")); + m_CBCheckFocus[i] = new wxCheckBox(m_Controller[i], IDCB_CHECKFOCUS, wxT("Allow out of focus input"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_AdvancedMapFilter[i] = new wxCheckBox(m_Controller[i], IDCB_FILTER_SETTINGS , wxT("No trigger filter")); + m_gStatusAdvancedSettings[i]->Add(m_CBCheckFocus[i], 0, (wxALL), 4); + m_gStatusAdvancedSettings[i]->Add(m_AdvancedMapFilter[i], 0, (wxALL), 4); + + // Tool tips + m_CBCheckFocus[i]->SetToolTip(wxT( + "Allow gamepad input even when Dolphin is not in focus. Out of focus keyboard input is never allowed.")); + m_AdvancedMapFilter[i]->SetToolTip(wxT( + "This will allow you to map a digital axis to the main stick or the C-stick. If you don't have" + " any analog triggers that will be automatically set when the trigger filter is off." + )); ////////////////////////// Advanced settings @@ -933,6 +961,7 @@ void ConfigBox::CreateGUIControls() m_sMainRight[i]->Add(m_gStatusIn[i], 0, wxEXPAND | (wxLEFT), 2); m_sMainRight[i]->Add(m_gStatusInSettings[i], 0, wxEXPAND | (wxLEFT | wxTOP), 2); m_sMainRight[i]->Add(m_gStatusTriggers[i], 0, wxEXPAND | (wxLEFT | wxTOP), 2); + m_sMainRight[i]->Add(m_gStatusAdvancedSettings[i], 0, wxEXPAND | (wxLEFT | wxTOP), 2); // -------------------------------------------------------------------- // Populate main sizer @@ -946,7 +975,7 @@ void ConfigBox::CreateGUIControls() m_sMainRight[i]->Show(g_Config.bShowAdvanced); // Don't allow these changes when running - if(emulator_running) + if(g_EmulatorRunning) { m_Joyname[i]->Enable(false); m_Joyattach[i]->Enable(false); @@ -979,7 +1008,9 @@ void ConfigBox::CreateGUIControls() // -------------------------------------------------------------------- // Debugging // ----------------------------- - //m_pStatusBar = new wxStaticText(this, IDT_DEBUGGING, wxT("Debugging"), wxPoint(135, 100), wxDefaultSize); + #ifdef SHOW_PAD_STATUS + m_pStatusBar = new wxStaticText(this, IDT_DEBUGGING, wxT("Debugging"), wxPoint(135, 100), wxDefaultSize); + #endif //m_pStatusBar2 = new wxStaticText(this, IDT_DEBUGGING2, wxT("Debugging2"), wxPoint(125, 200), wxDefaultSize); //m_pStatusBar->SetLabel(wxString::Format("Debugging text")); diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.h b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.h index 80823dc868..e47ba87b24 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.h +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.h @@ -48,6 +48,7 @@ #include #include +#include "../nJoy.h" class ConfigBox : public wxDialog { @@ -112,14 +113,15 @@ class ConfigBox : public wxDialog wxStaticBoxSizer *m_gGenSettingsID[4]; wxGridBagSizer * m_gGBGenSettings[4]; - wxCheckBox *m_CBSaveByID[4], *m_CBShowAdvanced[4], *m_CBCheckFocus[4]; + wxCheckBox *m_CBSaveByID[4], *m_CBShowAdvanced[4]; wxStaticText *m_TSControltype[4], *m_TSTriggerType[4]; - wxStaticBoxSizer *m_gStatusIn[4], *m_gStatusInSettings[4]; // Advanced settings + wxStaticBoxSizer *m_gStatusIn[4], *m_gStatusInSettings[4], *m_gStatusAdvancedSettings[4]; // Advanced settings wxBoxSizer *m_gStatusInSettingsH[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]; wxStaticBoxSizer *m_gStatusTriggers[4]; // Triggers wxStaticText *m_TStatusTriggers[4]; @@ -210,7 +212,7 @@ class ConfigBox : public wxDialog IDG_CONTROLLERTYPE, IDC_CONTROLTYPE, IDC_TRIGGERTYPE, // Controller type - IDC_SAVEBYID, IDC_SHOWADVANCED, IDC_CHECKFOCUS, // Settings + IDC_SAVEBYID, IDC_SHOWADVANCED, // Settings ID_INSTATUS1, ID_INSTATUS2, ID_INSTATUS3, ID_INSTATUS4, // Advanced status ID_STATUSBMP1, ID_STATUSBMP2, ID_STATUSBMP3, ID_STATUSBMP4, @@ -218,7 +220,7 @@ class ConfigBox : public wxDialog IDT_STATUS_IN, IDT_STATUS_OUT, // Advaced settings - IDCB_MAINSTICK_DIAGONAL, IDCB_MAINSTICK_S_TO_C, IDT_MAINSTICK_DIAGONAL, IDT_TRIGGERS, + IDCB_MAINSTICK_DIAGONAL, IDCB_MAINSTICK_S_TO_C, IDT_MAINSTICK_DIAGONAL, IDT_TRIGGERS, IDCB_CHECKFOCUS, IDCB_FILTER_SETTINGS, // Timers IDTM_CONSTANT, IDTM_BUTTON, @@ -317,7 +319,7 @@ class ConfigBox : public wxDialog wxBitmap CreateBitmap(); wxBitmap CreateBitmapDot(); void PadGetStatus(); void Update(); - void UpdateGUIKeys(int controller); + void UpdateGUIButtonMapping(int controller); void SaveButtonMapping(int controller, bool DontChangeId = false, int FromSlot = -1); void SaveButtonMappingAll(int Slot); void UpdateGUIAll(int Slot); diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp index faeadff75b..87b314ba22 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp @@ -39,13 +39,13 @@ #include "../nJoy.h" #include "Images/controller.xpm" -extern bool emulator_running; +extern bool g_EmulatorRunning; //////////////////////// // Set dialog items from saved values // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::UpdateGUIKeys(int controller) +void ConfigBox::UpdateGUIButtonMapping(int controller) { // http://wiki.wxwidgets.org/Converting_everything_to_and_from_wxString wxString tmp; @@ -56,22 +56,22 @@ void ConfigBox::UpdateGUIKeys(int controller) // Update the enabled checkbox m_Joyattach[controller]->SetValue(PadMapping[controller].enabled == 1 ? true : false); - tmp << PadMapping[controller].buttons[CTL_L_SHOULDER]; m_JoyShoulderL[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].buttons[CTL_R_SHOULDER]; m_JoyShoulderR[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].buttons[InputCommon::CTL_L_SHOULDER]; m_JoyShoulderL[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].buttons[InputCommon::CTL_R_SHOULDER]; m_JoyShoulderR[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].buttons[CTL_A_BUTTON]; m_JoyButtonA[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].buttons[CTL_B_BUTTON]; m_JoyButtonB[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].buttons[CTL_X_BUTTON]; m_JoyButtonX[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].buttons[CTL_Y_BUTTON]; m_JoyButtonY[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].buttons[CTL_Z_TRIGGER]; m_JoyButtonZ[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].buttons[InputCommon::CTL_A_BUTTON]; m_JoyButtonA[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].buttons[InputCommon::CTL_B_BUTTON]; m_JoyButtonB[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].buttons[InputCommon::CTL_X_BUTTON]; m_JoyButtonX[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].buttons[InputCommon::CTL_Y_BUTTON]; m_JoyButtonY[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].buttons[InputCommon::CTL_Z_TRIGGER]; m_JoyButtonZ[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].buttons[CTL_START]; m_JoyButtonStart[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].buttons[InputCommon::CTL_START]; m_JoyButtonStart[controller]->SetValue(tmp); tmp.clear(); tmp << PadMapping[controller].halfpress; m_JoyButtonHalfpress[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].axis[CTL_MAIN_X]; m_JoyAnalogMainX[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].axis[CTL_MAIN_Y]; m_JoyAnalogMainY[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].axis[CTL_SUB_X]; m_JoyAnalogSubX[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].axis[CTL_SUB_Y]; m_JoyAnalogSubY[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].axis[InputCommon::CTL_MAIN_X]; m_JoyAnalogMainX[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].axis[InputCommon::CTL_MAIN_Y]; m_JoyAnalogMainY[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].axis[InputCommon::CTL_SUB_X]; m_JoyAnalogSubX[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].axis[InputCommon::CTL_SUB_Y]; m_JoyAnalogSubY[controller]->SetValue(tmp); tmp.clear(); // Update the deadzone and controller type controls m_ControlType[controller]->SetSelection(PadMapping[controller].controllertype); @@ -79,20 +79,21 @@ void ConfigBox::UpdateGUIKeys(int controller) m_Deadzone[controller]->SetSelection(PadMapping[controller].deadzone); 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); //LogMsg("m_TriggerType[%i] = %i\n", controller, PadMapping[controller].triggertype); // Update D-Pad - if(PadMapping[controller].controllertype == CTL_DPAD_HAT) + if(PadMapping[controller].controllertype == InputCommon::CTL_DPAD_HAT) { - tmp << PadMapping[controller].dpad; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].dpad; m_JoyDpadDown[controller]->SetValue(tmp); tmp.clear(); } else { - tmp << PadMapping[controller].dpad2[CTL_D_PAD_UP]; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].dpad2[CTL_D_PAD_DOWN]; m_JoyDpadDown[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].dpad2[CTL_D_PAD_LEFT]; m_JoyDpadLeft[controller]->SetValue(tmp); tmp.clear(); - tmp << PadMapping[controller].dpad2[CTL_D_PAD_RIGHT]; m_JoyDpadRight[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_UP]; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_DOWN]; m_JoyDpadDown[controller]->SetValue(tmp); tmp.clear(); + tmp << PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_LEFT]; m_JoyDpadLeft[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 @@ -121,25 +122,25 @@ void ConfigBox::SaveButtonMapping(int controller, bool DontChangeId, int FromSlo PadMapping[controller].triggertype = m_TriggerType[FromSlot]->GetSelection(); PadMapping[controller].deadzone = m_Deadzone[FromSlot]->GetSelection(); PadMapping[controller].SDiagonal = m_CoBDiagonal[FromSlot]->GetLabel().mb_str(); - PadMapping[controller].bSquareToCircle = m_CBS_to_C[FromSlot]->IsChecked(); + PadMapping[controller].bSquareToCircle = m_CBS_to_C[FromSlot]->IsChecked(); // The analog buttons - m_JoyAnalogMainX[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[CTL_MAIN_X] = value; tmp.clear(); - m_JoyAnalogMainY[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[CTL_MAIN_Y] = value; tmp.clear(); - m_JoyAnalogSubX[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[CTL_SUB_X] = value; tmp.clear(); - m_JoyAnalogSubY[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[CTL_SUB_Y] = value; tmp.clear(); + m_JoyAnalogMainX[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[InputCommon::CTL_MAIN_X] = value; tmp.clear(); + m_JoyAnalogMainY[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[InputCommon::CTL_MAIN_Y] = value; tmp.clear(); + m_JoyAnalogSubX[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[InputCommon::CTL_SUB_X] = value; tmp.clear(); + m_JoyAnalogSubY[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[InputCommon::CTL_SUB_Y] = value; tmp.clear(); // The shoulder buttons - m_JoyShoulderL[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[CTL_L_SHOULDER] = value; - m_JoyShoulderR[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[CTL_R_SHOULDER] = value; + m_JoyShoulderL[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_L_SHOULDER] = value; + m_JoyShoulderR[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_R_SHOULDER] = value; // The digital buttons - m_JoyButtonA[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[CTL_A_BUTTON] = value; tmp.clear(); - m_JoyButtonB[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[CTL_B_BUTTON] = value; tmp.clear(); - m_JoyButtonX[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[CTL_X_BUTTON] = value; tmp.clear(); - m_JoyButtonY[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[CTL_Y_BUTTON] = value; tmp.clear(); - m_JoyButtonZ[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[CTL_Z_TRIGGER] = value; tmp.clear(); - m_JoyButtonStart[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[CTL_START] = value; tmp.clear(); + m_JoyButtonA[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_A_BUTTON] = value; tmp.clear(); + m_JoyButtonB[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_B_BUTTON] = value; tmp.clear(); + m_JoyButtonX[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_X_BUTTON] = value; tmp.clear(); + m_JoyButtonY[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_Y_BUTTON] = value; tmp.clear(); + m_JoyButtonZ[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_Z_TRIGGER] = value; tmp.clear(); + m_JoyButtonStart[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_START] = value; tmp.clear(); //LogMsg("PadMapping[%i].triggertype = %i, m_TriggerType[%i]->GetSelection() = %i\n", // controller, PadMapping[controller].triggertype, FromSlot, m_TriggerType[FromSlot]->GetSelection()); @@ -148,16 +149,16 @@ void ConfigBox::SaveButtonMapping(int controller, bool DontChangeId, int FromSlo m_JoyButtonHalfpress[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].halfpress = value; tmp.clear(); // The digital pad - if(PadMapping[controller].controllertype == CTL_DPAD_HAT) + if(PadMapping[controller].controllertype == InputCommon::CTL_DPAD_HAT) { - m_JoyDpadUp[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad = value; tmp.clear(); + m_JoyDpadDown[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad = value; tmp.clear(); } else { - m_JoyDpadUp[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[CTL_D_PAD_UP] = value; tmp.clear(); - m_JoyDpadDown[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[CTL_D_PAD_DOWN] = value; tmp.clear(); - m_JoyDpadLeft[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[CTL_D_PAD_LEFT] = value; tmp.clear(); - m_JoyDpadRight[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[CTL_D_PAD_RIGHT] = value; tmp.clear(); + m_JoyDpadUp[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_UP] = value; tmp.clear(); + m_JoyDpadDown[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_DOWN] = value; tmp.clear(); + m_JoyDpadLeft[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_LEFT] = value; tmp.clear(); + m_JoyDpadRight[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_RIGHT] = value; tmp.clear(); } // Replace "-1" with "" @@ -244,21 +245,6 @@ wxString ConfigBox::GetButtonText(int id, int Page) // ŻŻŻŻŻŻŻŻŻŻ -// Avoid extreme axis values -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -/* Function: We have to avoid very big values to becuse some triggers are -0x8000 in the - unpressed state (and then go from -0x8000 to 0x8000 as they are fully pressed) */ -bool AvoidValues(int value) -{ - // Avoid detecting very small or very big (for triggers) values - if( (value > -0x2000 && value < 0x2000) // Small values - || (value < -0x6000 || value > 0x6000)) // Big values - return true; // Avoid - else - return false; // Keep -} - - // Wait for button press // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ /* Loop or timer: There are basically two ways to do this. With a while() or for() loop, or with a @@ -271,6 +257,7 @@ void ConfigBox::GetButtons(wxCommandEvent& event) { DoGetButtons(event.GetId()); } + void ConfigBox::DoGetButtons(int GetId) { // ============================================= @@ -279,6 +266,17 @@ void ConfigBox::DoGetButtons(int GetId) // Get the current controller int Controller = notebookpage; + int PadID = PadMapping[Controller].ID; + + // Create a shortcut for the pad handle + SDL_Joystick *joy = PadState[Controller].joy; + + // Get the number of axes, hats and buttons + int Buttons = SDL_JoystickNumButtons(joy); + int Axes = SDL_JoystickNumAxes(joy); + int Hats = SDL_JoystickNumHats(joy); + + Console::Print("PadID: %i Axes: %i\n", PadID, joyinfo[PadID].NumAxes, joyinfo[PadID].joy); // Get the controller and trigger type int ControllerType = PadMapping[Controller].controllertype; @@ -288,35 +286,30 @@ void ConfigBox::DoGetButtons(int GetId) bool LeftRight = (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R); bool Axis = (GetId >= IDB_ANALOG_MAIN_X && GetId <= IDB_SHOULDER_R) - && !(TriggerType == CTL_TRIGGER_XINPUT && (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R) ); // Don't allow SDL here + && !(TriggerType == InputCommon::CTL_TRIGGER_XINPUT && (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R) ); // Don't allow SDL here - bool XInput = (TriggerType == CTL_TRIGGER_XINPUT); + bool XInput = (TriggerType == InputCommon::CTL_TRIGGER_XINPUT); bool Button = (GetId >= IDB_BUTTON_A && GetId <= IDB_BUTTONHALFPRESS) // All digital buttons || (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R) // both shoulder buttons - || (GetId >= IDB_DPAD_UP && GetId <= IDB_DPAD_RIGHT && ControllerType == CTL_DPAD_CUSTOM); // Or the custom hat mode + || (GetId >= IDB_DPAD_UP && GetId <= IDB_DPAD_RIGHT && ControllerType == InputCommon::CTL_DPAD_CUSTOM); // Or the custom hat mode bool Hat = (GetId >= IDB_DPAD_UP && GetId <= IDB_DPAD_RIGHT) // All DPads - && (PadMapping[Controller].controllertype == CTL_DPAD_HAT); // Not with the hat option defined + && (PadMapping[Controller].controllertype == InputCommon::CTL_DPAD_HAT); // Not with the hat option defined - /* Open a new joystick. Joysticks[controller].GetId is the system GetId of the physical joystick - that is mapped to controller, for example 0, 1, 2, 3 for the first four PadMapping */ - SDL_Joystick *joy = SDL_JoystickOpen(PadMapping[Controller].ID); + bool NoTriggerFilter = g_Config.bNoTriggerFilter; - // Get the number of axes, hats and buttons - int buttons = SDL_JoystickNumButtons(joy); - int axes = SDL_JoystickNumAxes(joy); - int hats = SDL_JoystickNumHats(joy); - - // Declare values + // Values used in this function char format[128]; - int value; // Axis value - int type; // Button type - bool Succeed = false; - bool Stop = false; // Stop the timer - int pressed = 0; int Seconds = 4; // Seconds to wait for int TimesPerSecond = 40; // How often to run the check + + // Values returned from InputCommon::GetButton() + int value; // Axis value + int type; // Button type + int pressed = 0; + bool Succeed = false; + bool Stop = false; // Stop the timer // ======================= //Console::Print("Before (%i) Id:%i %i IsRunning:%i\n", @@ -357,90 +350,10 @@ void ConfigBox::DoGetButtons(int GetId) // If there is a timer but we should not create a new one else { - // Update the internal status - SDL_JoystickUpdate(); - - // For the triggers we accept both a digital or an analog button - if(Axis) - { - for(int i = 0; i < axes; i++) - { - value = SDL_JoystickGetAxis(joy, i); - - if(AvoidValues(value)) continue; // Avoid values - - pressed = i + (LeftRight ? 1000 : 0); // Identify the analog triggers - type = CTL_AXIS; - Succeed = true; - } - } - - // Check for a hat - if(Hat) - { - for(int i = 0; i < hats; i++) - { - if(SDL_JoystickGetHat(joy, i)) - { - pressed = i; - type = CTL_HAT; - Succeed = true; - } - } - } - - // Check for a button - if(Button) - { - for(int i = 0; i < buttons; i++) - { - // Some kind of bug in SDL 1.3 would give button 9 and 10 (nonexistent) the value 48 on the 360 pad - if (SDL_JoystickGetButton(joy, i) > 1) continue; - - if(SDL_JoystickGetButton(joy, i)) - { - pressed = i; - type = CTL_BUTTON; - Succeed = true; - } - } - } - - // Check for a XInput trigger - #ifdef _WIN32 - if(XInput) - { - for(int i = 0; i <= XI_TRIGGER_R; i++) - { - if(XInput::GetXI(0, i)) - { - pressed = i + 1000; - type = CTL_AXIS; - Succeed = true; - } - } - } - #endif - - // Check for keyboard action - if (g_Pressed && Button) - { - // Todo: Add a separate keyboard vector to remove this restriction - if(g_Pressed >= buttons) - { - pressed = g_Pressed; - type = CTL_BUTTON; - Succeed = true; - g_Pressed = 0; - if(pressed == WXK_ESCAPE) pressed = -1; // Check for the exape key - } - else - { - pressed = g_Pressed; - g_Pressed = -1; - Stop = true; - } - } + InputCommon::GetButton( + joy, PadID, Buttons, Axes, Hats, + g_Pressed, value, type, pressed, Succeed, Stop, + LeftRight, Axis, XInput, Button, Hat, NoTriggerFilter); } // ========================= Check for keys @@ -507,9 +420,6 @@ void ConfigBox::DoGetButtons(int GetId) } // ======================== Process results - // We don't need this gamepad handle any more - if(SDL_JoystickOpened(PadMapping[Controller].ID)) SDL_JoystickClose(joy); - // Debugging /* Console::Print("Change: %i %i %i %i '%s' '%s' '%s' '%s'\n", @@ -517,5 +427,4 @@ void ConfigBox::DoGetButtons(int GetId) m_JoyButtonHalfpress[0]->GetValue().c_str(), m_JoyButtonHalfpress[1]->GetValue().c_str(), m_JoyButtonHalfpress[2]->GetValue().c_str(), m_JoyButtonHalfpress[3]->GetValue().c_str() );*/ } - /////////////////////////////////////////////////////////// Configure button mapping diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/SConscript b/Source/Plugins/Plugin_nJoy_SDL/Src/SConscript index e5e96b3d71..3b28332a6e 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/SConscript +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/SConscript @@ -25,7 +25,7 @@ if padenv['HAVE_WX']: padenv.Append( CXXFLAGS = [ '-fPIC' ], - LIBS = [ 'common' ], + LIBS = [ 'common', 'inputcommon' ], ) padenv.SharedLibrary(env['plugin_dir']+name, files) diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp index c5d9b1191e..7853dfafbb 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp @@ -81,13 +81,13 @@ // ŻŻŻŻŻŻŻŻŻ // Rumble in windows -#define _CONTROLLER_STATE_H // Avoid certain declarations in nJoy.h +#define _EXCLUDE_MAIN_ // Avoid certain declarations in nJoy.h FILE *pFile; HINSTANCE nJoy_hInst = NULL; -std::vector joyinfo; -CONTROLLER_STATE PadState[4]; -CONTROLLER_MAPPING PadMapping[4]; -bool emulator_running = false; +std::vector joyinfo; +InputCommon::CONTROLLER_STATE PadState[4]; +InputCommon::CONTROLLER_MAPPING PadMapping[4]; +bool g_EmulatorRunning = false; int NumPads = 0, NumGoodPads = 0; HWND m_hWnd; // Handle to window SPADInitialize *g_PADInitialize = NULL; @@ -191,9 +191,9 @@ void DllConfig(HWND _hParent) #ifdef _WIN32 // Start the pads so we can use them in the configuration and advanced controls - if(!emulator_running) + if(!g_EmulatorRunning) { - NumPads = Search_Devices(); // Populate joyinfo for all attached devices + Search_Devices(joyinfo, NumPads, NumGoodPads); // Populate joyinfo for all attached devices } m_frame = new ConfigBox(NULL); @@ -232,7 +232,7 @@ void DllDebugger(HWND _hParent, bool Show) {} // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ /* Information: This function can not be run twice without a Shutdown in between. If it's run twice the SDL_Init() will cause a crash. One solution to this is to keep a - global function that remembers the SDL_Init() and SDL_Quit() (emulator_running does + global function that remembers the SDL_Init() and SDL_Quit() (g_EmulatorRunning does not do that since we can open and close this without any game running). But I would suggest that avoiding to run this twice from the Core is better. */ void Initialize(void *init) @@ -241,7 +241,7 @@ void Initialize(void *init) //Console::Open(); Console::Print("Initialize: %i\n", SDL_WasInit(0)); g_PADInitialize = (SPADInitialize*)init; - emulator_running = true; + g_EmulatorRunning = true; #ifdef _DEBUG DEBUG_INIT(); @@ -251,7 +251,7 @@ void Initialize(void *init) m_hWnd = (HWND)g_PADInitialize->hWnd; #endif - NumPads = Search_Devices(); // Populate joyinfo for all attached devices + Search_Devices(joyinfo, NumPads, NumGoodPads); // Populate joyinfo for all attached devices /* Check if any of the pads failed to open. In Windows there is a strange "IDirectInputDevice2:: SetDataFormat() DirectX error -2147024809" after a few Open and Close */ @@ -265,79 +265,15 @@ void Initialize(void *init) } } - -// Search attached devices. Populate joyinfo for all attached physical devices. -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -int Search_Devices() +bool Search_Devices(std::vector &_joyinfo, int &_NumPads, int &_NumGoodPads) { - // Load config - #ifdef _DEBUG - DEBUG_INIT(); - #endif - - /* SDL 1.3 use DirectInput instead of the old Microsoft Multimeda API, and with this we need - the SDL_INIT_VIDEO flag to */ - if (!SDL_WasInit(0)) - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) - { - PanicAlert("Could not initialize SDL: %s", SDL_GetError()); - return 0; - } - - #ifdef _DEBUG - fprintf(pFile, "Scanning for devices\n"); - fprintf(pFile, "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ\n"); - #endif - - // Get device status - int numjoy = SDL_NumJoysticks(); - for (int i = 0; i < numjoy; i++ ) - { - CONTROLLER_INFO Tmp; - - Tmp.joy = SDL_JoystickOpen(i); - Tmp.ID = i; - Tmp.NumAxes = SDL_JoystickNumAxes(Tmp.joy); - Tmp.NumButtons = SDL_JoystickNumButtons(Tmp.joy); - Tmp.NumBalls = SDL_JoystickNumBalls(Tmp.joy); - Tmp.NumHats = SDL_JoystickNumHats(Tmp.joy); - Tmp.Name = SDL_JoystickName(i); - - // Check if the device is okay - if ( Tmp.NumAxes == 0 - && Tmp.NumBalls == 0 - && Tmp.NumButtons == 0 - && Tmp.NumHats == 0 - ) - { - Tmp.Good = false; - } - else - { - NumGoodPads++; - Tmp.Good = true; - } - - joyinfo.push_back(Tmp); - - #ifdef _DEBUG - fprintf(pFile, "ID: %d\n", i); - fprintf(pFile, "Name: %s\n", joyinfo[i].Name); - fprintf(pFile, "Buttons: %d\n", joyinfo[i].NumButtons); - fprintf(pFile, "Axes: %d\n", joyinfo[i].NumAxes); - fprintf(pFile, "Hats: %d\n", joyinfo[i].NumHats); - fprintf(pFile, "Balls: %d\n\n", joyinfo[i].NumBalls); - #endif - - // We have now read the values we need so we close the device - if (SDL_JoystickOpened(i)) SDL_JoystickClose(joyinfo[i].joy); - } + bool Success = InputCommon::SearchDevices(_joyinfo, _NumPads, _NumGoodPads); // Warn the user if no gamepads are detected - if (NumGoodPads == 0 && emulator_running) + if (_NumGoodPads == 0 && g_EmulatorRunning) { PanicAlert("nJoy: No Gamepad Detected"); - return joyinfo.size(); + return false; } // Load PadMapping[] etc @@ -351,7 +287,7 @@ int Search_Devices() PadState[i].joy = SDL_JoystickOpen(PadMapping[i].ID); } - return joyinfo.size(); + return Success; } // Shutdown PAD (stop emulation) @@ -372,18 +308,17 @@ void Shutdown() if(SDL_JoystickOpened(PadMapping[i].ID)) SDL_JoystickClose(PadState[i].joy); } - SDL_Quit(); + // Clear the physical device info + joyinfo.clear(); + + // Finally close SDL + if (SDL_WasInit(0)) SDL_Quit(); #ifdef _DEBUG DEBUG_QUIT(); #endif - // Clear the physical device info - //delete [] joyinfo; - //joyinfo = NULL; - joyinfo.clear(); - - emulator_running = false; + g_EmulatorRunning = false; #ifdef _WIN32 #ifdef USE_RUMBLE_DINPUT_HACK @@ -405,13 +340,13 @@ void PAD_Input(u16 _Key, u8 _UpDown) // Check if the keys are interesting, and then update it for(int i = 0; i < 4; i++) { - for(int j = CTL_L_SHOULDER; j <= CTL_START; j++) + for(int j = InputCommon::CTL_L_SHOULDER; j <= InputCommon::CTL_START; j++) { if (PadMapping[i].buttons[j] == _Key) { PadState[i].buttons[j] = _UpDown; break; } } - for(int j = CTL_D_PAD_UP; j <= CTL_D_PAD_RIGHT; j++) + for(int j = InputCommon::CTL_D_PAD_UP; j <= InputCommon::CTL_D_PAD_RIGHT; j++) { if (PadMapping[i].dpad2[j] == _Key) { PadState[i].dpad2[j] = _UpDown; break; } @@ -461,8 +396,9 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) // Clear pad status memset(_pPADStatus, 0, sizeof(SPADStatus)); - // Update the pad status - GetJoyState(_numPAD); + // Check that Dolphin is in focus, otherwise don't update the pad status + if (!g_Config.bCheckFocus && IsFocus()) + GetJoyState(PadState[_numPAD], PadMapping[_numPAD], _numPAD, joyinfo[PadMapping[_numPAD].ID].NumButtons); // Get type int TriggerType = PadMapping[_numPAD].triggertype; @@ -472,32 +408,32 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) // ----------- // Read axis values - int i_main_stick_x = PadState[_numPAD].axis[CTL_MAIN_X]; - int i_main_stick_y = -PadState[_numPAD].axis[CTL_MAIN_Y]; - int i_sub_stick_x = PadState[_numPAD].axis[CTL_SUB_X]; - int i_sub_stick_y = -PadState[_numPAD].axis[CTL_SUB_Y]; - int TriggerLeft = PadState[_numPAD].axis[CTL_L_SHOULDER]; - int TriggerRight = PadState[_numPAD].axis[CTL_R_SHOULDER]; + int i_main_stick_x = PadState[_numPAD].axis[InputCommon::CTL_MAIN_X]; + int i_main_stick_y = -PadState[_numPAD].axis[InputCommon::CTL_MAIN_Y]; + int i_sub_stick_x = PadState[_numPAD].axis[InputCommon::CTL_SUB_X]; + int i_sub_stick_y = -PadState[_numPAD].axis[InputCommon::CTL_SUB_Y]; + int TriggerLeft = PadState[_numPAD].axis[InputCommon::CTL_L_SHOULDER]; + int TriggerRight = PadState[_numPAD].axis[InputCommon::CTL_R_SHOULDER]; // Check if we should make adjustments if(PadMapping[_numPAD].bSquareToCircle) { - std::vector main_xy = Pad_Square_to_Circle(i_main_stick_x, i_main_stick_y, _numPAD); + std::vector main_xy = InputCommon::Pad_Square_to_Circle(i_main_stick_x, i_main_stick_y, _numPAD, PadMapping[_numPAD]); i_main_stick_x = main_xy.at(0); i_main_stick_y = main_xy.at(1); } // Convert axis values - u8 main_stick_x = Pad_Convert(i_main_stick_x); - u8 main_stick_y = Pad_Convert(i_main_stick_y); - u8 sub_stick_x = Pad_Convert(i_sub_stick_x); - u8 sub_stick_y = Pad_Convert(i_sub_stick_y); + u8 main_stick_x = InputCommon::Pad_Convert(i_main_stick_x); + u8 main_stick_y = InputCommon::Pad_Convert(i_main_stick_y); + u8 sub_stick_x = InputCommon::Pad_Convert(i_sub_stick_x); + 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 == CTL_TRIGGER_SDL) + if(PadMapping[_numPAD].triggertype == InputCommon::CTL_TRIGGER_SDL) { - if(PadMapping[_numPAD].buttons[CTL_L_SHOULDER] >= 1000) TriggerLeft = Pad_Convert(TriggerLeft); - if(PadMapping[_numPAD].buttons[CTL_R_SHOULDER] >= 1000) TriggerRight = 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?) @@ -520,7 +456,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) _pPADStatus->button |= PAD_USE_ORIGIN; // Neutral value, no button pressed // Check if the digital L button is pressed - if (PadState[_numPAD].buttons[CTL_L_SHOULDER]) + if (PadState[_numPAD].buttons[InputCommon::CTL_L_SHOULDER]) { _pPADStatus->button |= PAD_TRIGGER_L; _pPADStatus->triggerLeft = TriggerValue; @@ -529,7 +465,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) _pPADStatus->triggerLeft = TriggerLeft; // Check if the digital R button is pressed - if (PadState[_numPAD].buttons[CTL_R_SHOULDER]) + if (PadState[_numPAD].buttons[InputCommon::CTL_R_SHOULDER]) { _pPADStatus->button |= PAD_TRIGGER_R; _pPADStatus->triggerRight = TriggerValue; @@ -545,26 +481,26 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) /////////////////////////////////////////////////// // The digital buttons // ----------- - if (PadState[_numPAD].buttons[CTL_A_BUTTON]) + if (PadState[_numPAD].buttons[InputCommon::CTL_A_BUTTON]) { _pPADStatus->button |= PAD_BUTTON_A; _pPADStatus->analogA = 255; // Perhaps support pressure? } - if (PadState[_numPAD].buttons[CTL_B_BUTTON]) + if (PadState[_numPAD].buttons[InputCommon::CTL_B_BUTTON]) { _pPADStatus->button |= PAD_BUTTON_B; _pPADStatus->analogB = 255; // Perhaps support pressure? } - if (PadState[_numPAD].buttons[CTL_X_BUTTON]) _pPADStatus->button|=PAD_BUTTON_X; - if (PadState[_numPAD].buttons[CTL_Y_BUTTON]) _pPADStatus->button|=PAD_BUTTON_Y; - if (PadState[_numPAD].buttons[CTL_Z_TRIGGER]) _pPADStatus->button|=PAD_TRIGGER_Z; - if (PadState[_numPAD].buttons[CTL_START]) _pPADStatus->button|=PAD_BUTTON_START; + if (PadState[_numPAD].buttons[InputCommon::CTL_X_BUTTON]) _pPADStatus->button|=PAD_BUTTON_X; + if (PadState[_numPAD].buttons[InputCommon::CTL_Y_BUTTON]) _pPADStatus->button|=PAD_BUTTON_Y; + if (PadState[_numPAD].buttons[InputCommon::CTL_Z_TRIGGER]) _pPADStatus->button|=PAD_TRIGGER_Z; + if (PadState[_numPAD].buttons[InputCommon::CTL_START]) _pPADStatus->button|=PAD_BUTTON_START; /////////////////////////////////////////////////// // The D-pad // ----------- - if (PadMapping[_numPAD].controllertype == CTL_DPAD_HAT) + if (PadMapping[_numPAD].controllertype == InputCommon::CTL_DPAD_HAT) { if (PadState[_numPAD].dpad == SDL_HAT_LEFTUP || PadState[_numPAD].dpad == SDL_HAT_UP || PadState[_numPAD].dpad == SDL_HAT_RIGHTUP ) _pPADStatus->button|=PAD_BUTTON_UP; if (PadState[_numPAD].dpad == SDL_HAT_LEFTUP || PadState[_numPAD].dpad == SDL_HAT_LEFT || PadState[_numPAD].dpad == SDL_HAT_LEFTDOWN ) _pPADStatus->button|=PAD_BUTTON_LEFT; @@ -573,13 +509,13 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) } else { - if (PadState[_numPAD].dpad2[CTL_D_PAD_UP]) + if (PadState[_numPAD].dpad2[InputCommon::CTL_D_PAD_UP]) _pPADStatus->button |= PAD_BUTTON_UP; - if (PadState[_numPAD].dpad2[CTL_D_PAD_DOWN]) + if (PadState[_numPAD].dpad2[InputCommon::CTL_D_PAD_DOWN]) _pPADStatus->button |= PAD_BUTTON_DOWN; - if (PadState[_numPAD].dpad2[CTL_D_PAD_LEFT]) + if (PadState[_numPAD].dpad2[InputCommon::CTL_D_PAD_LEFT]) _pPADStatus->button |= PAD_BUTTON_LEFT; - if (PadState[_numPAD].dpad2[CTL_D_PAD_RIGHT]) + if (PadState[_numPAD].dpad2[InputCommon::CTL_D_PAD_RIGHT]) _pPADStatus->button |= PAD_BUTTON_RIGHT; } @@ -645,226 +581,7 @@ bool IsFocus() } -////////////////////////////////////////////////////////////////////////////////////////// -// Convert stick values -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -/* Convert stick values. - - The value returned by SDL_JoystickGetAxis is a signed integer s16 - (-32768 to 32767). The value used for the gamecube controller is an unsigned - char u8 (0 to 255) with neutral at 0x80 (128), so that it's equivalent to a signed - -128 to 127. -*/ -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -int Pad_Convert(int _val) -{ - /* If the limits on PadState[].axis[] actually is a u16 then we don't need this - but if it's not actually limited to that we need to apply these limits */ - if(_val > 32767) _val = 32767; // upper limit - if(_val < -32768) _val = -32768; // lower limit - - // Convert the range (-0x8000 to 0x7fff) to (0 to 0xffff) - _val = 0x8000 +_val; - - // Convert the range (-32768 to 32767) to (-128 to 127) - _val = _val >> 8; - - //Console::Print("0x%04x %06i\n\n", _val, _val); - - return _val; -} - - -/* Convert the stick raidus from a circular to a square. I don't know what input values - the actual GC controller produce for the GC, it may be a square, a circle or something - in between. But one thing that is certain is that PC pads differ in their output (as - shown in the list below), so it may be beneficiary to convert whatever radius they - produce to the radius the GC games expect. This is the first implementation of this - that convert a square radius to a circual radius. Use the advanced settings to enable - and calibrate it. - - Observed diagonals: - Perfect circle: 71% = sin(45) - Logitech Dual Action: 100% - Dual Shock 2 (Original) with Super Dual Box Pro: 90% - XBox 360 Wireless: 85% - GameCube Controller (Third Party) with EMS TrioLinker Plus II: 60% -*/ -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -float SquareDistance(float deg) -{ - // See if we have to adjust the angle - deg = abs(deg); - if( (deg > 45 && deg < 135) ) deg = deg - 90; - - float rad = deg * M_PI / 180; - - float val = abs(cos(rad)); - float dist = 1 / val; // Calculate distance from center - - //m_frame->m_pStatusBar2->SetLabel(wxString::Format("Deg:%f Val:%f Dist:%f", deg, val, dist)); - - return dist; -} -std::vector Pad_Square_to_Circle(int _x, int _y, int _pad) -{ - /* Do we need this? */ - if(_x > 32767) _x = 32767; if(_y > 32767) _y = 32767; // upper limit - if(_x < -32768) _x = -32768; if(_y > 32767) _y = 32767; // lower limit - - // ==================================== - // Convert to circle - // ----------- - int Tmp = atoi (PadMapping[_pad].SDiagonal.substr(0, PadMapping[_pad].SDiagonal.length() - 1).c_str()); - float Diagonal = Tmp / 100.0; - - // First make a perfect square in case we don't have one already - float OrigDist = sqrt( pow((float)_y, 2) + pow((float)_x, 2) ); // Get current distance - float rad = atan2((float)_y, (float)_x); // Get current angle - float deg = rad * 180 / M_PI; - - // A diagonal of 85% means a distance of 1.20 - float corner_circle_dist = ( Diagonal / sin(45 * M_PI / 180) ); - float SquareDist = SquareDistance(deg); - float adj_ratio1; // The original-to-square distance adjustment - float adj_ratio2 = SquareDist; // The circle-to-square distance adjustment - // float final_ratio; // The final adjustment to the current distance //TODO: This is not used - float result_dist; // The resulting distance - - // Calculate the corner-to-square adjustment ratio - if(corner_circle_dist < SquareDist) adj_ratio1 = SquareDist / corner_circle_dist; - else adj_ratio1 = 1; - - // Calculate the resulting distance - result_dist = OrigDist * adj_ratio1 / adj_ratio2; - - float x = result_dist * cos(rad); // calculate x - float y = result_dist * sin(rad); // calculate y - - int int_x = (int)floor(x); - int int_y = (int)floor(y); - - // Debugging - //m_frame->m_pStatusBar2->SetLabel(wxString::Format("%f %f %i", corner_circle_dist, Diagonal, Tmp)); - - std::vector vec; - vec.push_back(int_x); - vec.push_back(int_y); - return vec; -} -///////////////////////////////////////////////////////////////////// Convert stick values -////////////////////////////////////////////////////////////////////////////////////////// -// Supporting functions -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ - -// Read current joystick status -/* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ - The value PadMapping[].buttons[] is the number of the assigned joypad button, - PadState[].buttons[] is the status of the button, it becomes 0 (no pressed) or 1 (pressed) */ - - -// Read buttons status. Called from GetJoyState(). -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ReadButton(int controller, int button) -{ - int ctl_button = PadMapping[controller].buttons[button]; - if (ctl_button < joyinfo[PadMapping[controller].ID].NumButtons) - { - PadState[controller].buttons[button] = SDL_JoystickGetButton(PadState[controller].joy, ctl_button); - } -} - -// Request joystick state. -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -/* Called from: PAD_GetStatus() - Input: The virtual device 0, 1, 2 or 3 - Function: Updates the PadState struct with the current pad status. The input value "controller" is - for a virtual controller 0 to 3. */ -void GetJoyState(int controller) -{ - // Check that Dolphin is in focus, otherwise don't update the pad status - if (!g_Config.bCheckFocus && !IsFocus()) return; - - // Update the gamepad status - SDL_JoystickUpdate(); - - // Save the number of buttons - int Buttons = joyinfo[PadMapping[controller].ID].NumButtons; - - // Update axis states. It doesn't hurt much if we happen to ask for nonexisting axises here. - PadState[controller].axis[CTL_MAIN_X] = SDL_JoystickGetAxis(PadState[controller].joy, PadMapping[controller].axis[CTL_MAIN_X]); - PadState[controller].axis[CTL_MAIN_Y] = SDL_JoystickGetAxis(PadState[controller].joy, PadMapping[controller].axis[CTL_MAIN_Y]); - PadState[controller].axis[CTL_SUB_X] = SDL_JoystickGetAxis(PadState[controller].joy, PadMapping[controller].axis[CTL_SUB_X]); - PadState[controller].axis[CTL_SUB_Y] = SDL_JoystickGetAxis(PadState[controller].joy, PadMapping[controller].axis[CTL_SUB_Y]); - - // Update the analog trigger axis values -#ifdef _WIN32 - if (PadMapping[controller].triggertype == CTL_TRIGGER_SDL) - { -#endif - // If we are using SDL analog triggers the buttons have to be mapped as 1000 or up, otherwise they are not used - if(PadMapping[controller].buttons[CTL_L_SHOULDER] >= 1000) PadState[controller].axis[CTL_L_SHOULDER] = SDL_JoystickGetAxis(PadState[controller].joy, PadMapping[controller].buttons[CTL_L_SHOULDER] - 1000); else PadState[controller].axis[CTL_L_SHOULDER] = 0; - if(PadMapping[controller].buttons[CTL_R_SHOULDER] >= 1000) PadState[controller].axis[CTL_R_SHOULDER] = SDL_JoystickGetAxis(PadState[controller].joy, PadMapping[controller].buttons[CTL_R_SHOULDER] - 1000); else PadState[controller].axis[CTL_R_SHOULDER] = 0; -#ifdef _WIN32 - } - else - { - PadState[controller].axis[CTL_L_SHOULDER] = XInput::GetXI(0, PadMapping[controller].buttons[CTL_L_SHOULDER] - 1000); - PadState[controller].axis[CTL_R_SHOULDER] = XInput::GetXI(0, PadMapping[controller].buttons[CTL_R_SHOULDER] - 1000); - } -#endif - - // Update button states to on or off - ReadButton(controller, CTL_L_SHOULDER); - ReadButton(controller, CTL_R_SHOULDER); - ReadButton(controller, CTL_A_BUTTON); - ReadButton(controller, CTL_B_BUTTON); - ReadButton(controller, CTL_X_BUTTON); - ReadButton(controller, CTL_Y_BUTTON); - ReadButton(controller, CTL_Z_TRIGGER); - ReadButton(controller, CTL_START); - - // - if (PadMapping[controller].halfpress < joyinfo[controller].NumButtons) - PadState[controller].halfpress = SDL_JoystickGetButton(PadState[controller].joy, PadMapping[controller].halfpress); - - // Check if we have an analog or digital joypad - if (PadMapping[controller].controllertype == CTL_DPAD_HAT) - { - PadState[controller].dpad = SDL_JoystickGetHat(PadState[controller].joy, PadMapping[controller].dpad); - } - else - { - /* Only do this if the assigned button is in range (to allow for the current way of saving keyboard - keys in the same array) */ - if(PadMapping[controller].dpad2[CTL_D_PAD_UP] <= Buttons) - PadState[controller].dpad2[CTL_D_PAD_UP] = SDL_JoystickGetButton(PadState[controller].joy, PadMapping[controller].dpad2[CTL_D_PAD_UP]); - if(PadMapping[controller].dpad2[CTL_D_PAD_DOWN] <= Buttons) - PadState[controller].dpad2[CTL_D_PAD_DOWN] = SDL_JoystickGetButton(PadState[controller].joy, PadMapping[controller].dpad2[CTL_D_PAD_DOWN]); - if(PadMapping[controller].dpad2[CTL_D_PAD_LEFT] <= Buttons) - PadState[controller].dpad2[CTL_D_PAD_LEFT] = SDL_JoystickGetButton(PadState[controller].joy, PadMapping[controller].dpad2[CTL_D_PAD_LEFT]); - if(PadMapping[controller].dpad2[CTL_D_PAD_RIGHT] <= Buttons) - PadState[controller].dpad2[CTL_D_PAD_RIGHT] = SDL_JoystickGetButton(PadState[controller].joy, PadMapping[controller].dpad2[CTL_D_PAD_RIGHT]); - } - - /* Debugging - Console::ClearScreen(); - Console::Print( - "Controller and handle: %i %i\n" - - "Triggers:%i %i %i %i %i | HalfPress: %i Mapping: %i\n", - - controller, (int)PadState[controller].joy, - - PadMapping[controller].triggertype, - PadMapping[controller].buttons[CTL_L_SHOULDER], PadMapping[controller].buttons[CTL_R_SHOULDER], - PadState[controller].axis[CTL_L_SHOULDER], PadState[controller].axis[CTL_R_SHOULDER], - - PadState[controller].halfpress, PadMapping[controller].halfpress - ); */ -} -////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h index 9295304e7e..669d7907e4 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h @@ -35,6 +35,9 @@ // ŻŻŻŻŻŻŻŻŻŻ // Set this if you want to use the rumble 'hack' for controller one //#define USE_RUMBLE_DINPUT_HACK + +// Show a status window with the detected axes, buttons and so on +//#define SHOW_PAD_STATUS ////////////////////////// @@ -45,7 +48,9 @@ #include #include #include -#include + +#include "../../../Core/InputCommon/Src/SDL.h" // Core +#include "../../../Core/InputCommon/Src/XInput.h" #include "Common.h" // Common #include "pluginspecs_pad.h" @@ -54,7 +59,6 @@ //#include "Timer.h" #include "Config.h" // Local -#include "XInput.h" #if defined(HAVE_WX) && HAVE_WX #include "GUI/AboutBox.h" @@ -102,115 +106,6 @@ #define THANKYOU "`plot`, Absolute0, Aprentice, Bositman, Brice, ChaosCode, CKemu, CoDeX, Dave2001, dn, drk||Raziel, Florin, Gent, Gigaherz, Hacktarux, JegHegy, Linker, Linuzappz, Martin64, Muad, Knuckles, Raziel, Refraction, Rudy_x, Shadowprince, Snake785, Saqib, vEX, yaz0r, Zilmar, Zenogais and ZeZu." -////////////////////////////////////////////////////////////////////////////////////////// -// Structures -/* ŻŻŻŻŻŻŻŻŻŻ - CONTROLLER_STATE buttons (PadState) = 0 or 1 - CONTROLLER_MAPPING buttons (joystick) = 0 or 1, 2, 3, 4, a certain joypad button - - Please remember: The axis limit is hardcoded here, if you allow more axises (for - example for analog A and B buttons) you must first incrase the size of the axis array - size here - */ -struct CONTROLLER_STATE // GC PAD INFO/STATE -{ - int buttons[8]; // Amount of buttons (A B X Y Z, L-Trigger R-Trigger Start) might need to change the triggers buttons - int dpad; // Automatic SDL D-Pad (8 directions + neutral) - int dpad2[4]; // D-pad using buttons - int axis[6]; // 2 x 2 Axes (Main & Sub) - int halfpress; // Halfpress... you know, like not fully pressed ;)... - SDL_Joystick *joy; // SDL joystick device -}; - -struct CONTROLLER_MAPPING // GC PAD MAPPING -{ - int buttons[8]; // (See above) - int dpad; // (See above) - int dpad2[4]; // (See above) - int axis[6]; // (See above) - int halfpress; // (See above) - int enabled; // Pad attached? - int deadzone; // Deadzone... what else? - int ID; // SDL joystick device ID - int controllertype; // Hat: Hat or custom buttons - int triggertype; // Triggers range - std::string SDiagonal; - bool bSquareToCircle; - int eventnum; // Linux Event Number, Can't be found dynamically yet -}; - -struct CONTROLLER_INFO // CONNECTED WINDOWS DEVICES INFO -{ - int NumAxes; // Amount of Axes - int NumButtons; // Amount of Buttons - int NumBalls; // Amount of Balls - int NumHats; // Amount of Hats (POV) - std::string Name; // Joypad/stickname - int ID; // SDL joystick device ID - bool Good; - SDL_Joystick *joy; // SDL joystick device -}; - -enum -{ - // CTL_L_SHOULDER and CTL_R_SHOULDER = 0 and 1 - CTL_MAIN_X = 2, - CTL_MAIN_Y, - CTL_SUB_X, - CTL_SUB_Y -}; - -enum -{ - CTL_L_SHOULDER = 0, - CTL_R_SHOULDER, - CTL_A_BUTTON, - CTL_B_BUTTON, - CTL_X_BUTTON, - CTL_Y_BUTTON, - CTL_Z_TRIGGER, - CTL_START -}; - -// DPad Type -enum -{ - CTL_DPAD_HAT = 0, // Automatically use the first hat that SDL finds - CTL_DPAD_CUSTOM // Custom directional pad settings -}; - -// Trigger Type -enum -{ - CTL_TRIGGER_SDL = 0, // - CTL_TRIGGER_XINPUT // The XBox 360 pad -}; - -enum -{ - CTL_D_PAD_UP = 0, - CTL_D_PAD_DOWN, - CTL_D_PAD_LEFT, - CTL_D_PAD_RIGHT -}; - -// Button type for the configuration -enum -{ - CTL_AXIS = 0, - CTL_HAT, - CTL_BUTTON, - CTL_KEY -}; - -// XInput buttons -enum -{ - XI_TRIGGER_L = 0, - XI_TRIGGER_R -}; - - ////////////////////////////////////////////////////////////////////////////////////////// // Input vector. Todo: Save the configured keys here instead of in joystick // ŻŻŻŻŻŻŻŻŻ @@ -225,11 +120,11 @@ extern std::vector Keys; ////////////////////////////////////////////////////////////////////////////////////////// // Variables // ŻŻŻŻŻŻŻŻŻ -#ifndef _CONTROLLER_STATE_H +#ifndef _EXCLUDE_MAIN_ extern FILE *pFile; - extern std::vector joyinfo; - extern CONTROLLER_STATE PadState[4]; - extern CONTROLLER_MAPPING PadMapping[4]; + extern std::vector joyinfo; + extern InputCommon::CONTROLLER_STATE PadState[4]; + extern InputCommon::CONTROLLER_MAPPING PadMapping[4]; extern HWND m_hWnd; // Handle to window extern int NumPads, NumGoodPads; // Number of goods pads #endif @@ -238,16 +133,12 @@ extern std::vector Keys; ////////////////////////////////////////////////////////////////////////////////////////// // Custom Functions // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ - -void GetJoyState(int controller); -int Search_Devices(); +bool Search_Devices(std::vector &_joyinfo, int &_NumPads, int &_NumGoodPads); void DEBUG_INIT(); void DEBUG_QUIT(); bool IsFocus(); void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus); // Rumble -int Pad_Convert(int _val); // Value conversion -std::vector Pad_Square_to_Circle(int _x, int _y, int _pad); // Value conversion //void SaveConfig(); //void LoadConfig();