diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 6293490eee..3d7ca44444 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -145,6 +145,14 @@ bool GetRealWiimote() { return g_bRealWiimote; } +// This can occur when the emulator is not running and the nJoy configuration window is opened +void ReconnectPad() +{ + CPluginManager &Plugins = CPluginManager::GetInstance(); + Plugins.FreePad(0); + Plugins.GetPad(0)->Config(g_pWindowHandle); + Console::Print("ReconnectPad()\n"); +} // This doesn't work yet, I don't understand how the connection work yet void ReconnectWiimote() { diff --git a/Source/Core/Core/Src/Core.h b/Source/Core/Core/Src/Core.h index 3dcf8ae49b..0cd70634d9 100644 --- a/Source/Core/Core/Src/Core.h +++ b/Source/Core/Core/Src/Core.h @@ -61,6 +61,7 @@ namespace Core void* GetWindowHandle(); bool GetRealWiimote(); void ReconnectWiimote(); + void ReconnectPad(); extern bool bReadTrace; extern bool bWriteTrace; diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index 38dcfae8b1..ffee57e50a 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -47,7 +47,6 @@ be accessed from Core::GetWindowHandle(). #include "Common.h" // Common #include "FileUtil.h" #include "Timer.h" -#include "ConsoleWindow.h" #include "ConfigManager.h" // Core #include "Core.h" @@ -184,16 +183,16 @@ int abc = 0; case NJOY_RELOAD: // DirectInput in nJoy has failed + Core::ReconnectPad(); return 0; case WIIMOTE_RECONNECT: // The Wiimote plugin has been shut down, now reconnect the Wiimote - Console::Print("WIIMOTE_RECONNECT\n"); + //Console::Print("WIIMOTE_RECONNECT\n"); Core::ReconnectWiimote(); return 0; } break; - //default: // return wxPanel::MSWWindowProc(nMsg, wParam, lParam); } diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 036f8217bd..40b7a70f72 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -48,6 +48,7 @@ be accessed from Core::GetWindowHandle(). #include "Common.h" // Common #include "FileUtil.h" #include "Timer.h" +#include "ConsoleWindow.h" #include "ConfigManager.h" // Core #include "Core.h" @@ -537,7 +538,7 @@ void CFrame::OnPluginDSP(wxCommandEvent& WXUNUSED (event)) void CFrame::OnPluginPAD(wxCommandEvent& WXUNUSED (event)) { CPluginManager::GetInstance().OpenConfig( - GetHandle(), + m_Panel->GetHandle(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strPadPlugin[0].c_str(), PLUGIN_TYPE_PAD ); diff --git a/Source/Core/InputCommon/Src/SDL.cpp b/Source/Core/InputCommon/Src/SDL.cpp index 6967e6c489..2c20379394 100644 --- a/Source/Core/InputCommon/Src/SDL.cpp +++ b/Source/Core/InputCommon/Src/SDL.cpp @@ -38,6 +38,13 @@ //////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +// Definitions +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +int g_LastPad = 0; +//////////////////////////////////// + + namespace InputCommon { @@ -150,7 +157,7 @@ void ReadButton(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int 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(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int controller, int NumButtons) +void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int Controller, int NumButtons) { // Update the gamepad status SDL_JoystickUpdate(); @@ -211,21 +218,34 @@ void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, in _PadState.dpad2[CTL_D_PAD_RIGHT] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_RIGHT]); } - /* Debugging - Console::ClearScreen(); + #ifdef SHOW_PAD_STATUS + // Show the status of all connected pads + if ((g_LastPad == 0 && Controller == 0) || Controller < g_LastPad) Console::ClearScreen(); + g_LastPad = Controller; Console::Print( - "Controller and handle: %i %i\n" + "Pad | Number:%i Enabled:%i Handle:%i\n" + "Main Stick | X:%03i Y:%03i\n" + "Trigger | Type:%s DigitalL:%i DigitalR:%i AnalogL:%03i AnalogR:%03i HalfPress:%i\n" + "Buttons | A:%i X:%i\n" + "D-Pad | Type:%s Hat:%i U:%i D:%i\n" + "======================================================\n", - "Triggers:%i %i %i %i %i | HalfPress: %i Mapping: %i\n", + Controller, _PadMapping.enabled, _PadState.joy, - controller, (int)_PadState.joy, + _PadState.axis[InputCommon::CTL_MAIN_X], _PadState.axis[InputCommon::CTL_MAIN_Y], - _PadMapping.triggertype, - _PadMapping.buttons[CTL_L_SHOULDER], _PadMapping.buttons[CTL_R_SHOULDER], - _PadState.axis[CTL_L_SHOULDER], _PadState.axis[CTL_R_SHOULDER], + (_PadMapping.triggertype ? "CTL_TRIGGER_XINPUT" : "CTL_TRIGGER_SDL"), + _PadState.buttons[InputCommon::CTL_L_SHOULDER], _PadState.buttons[InputCommon::CTL_R_SHOULDER], + _PadState.axis[InputCommon::CTL_L_SHOULDER], _PadState.axis[InputCommon::CTL_R_SHOULDER], + _PadState.halfpress, - _PadState.halfpress, _PadMapping.halfpress - ); */ + _PadState.buttons[InputCommon::CTL_A_BUTTON], _PadState.buttons[InputCommon::CTL_X_BUTTON], + + (_PadMapping.controllertype ? "CTL_DPAD_CUSTOM" : "CTL_DPAD_HAT"), + _PadState.dpad, + _PadState.dpad2[InputCommon::CTL_D_PAD_UP], _PadState.dpad2[InputCommon::CTL_D_PAD_DOWN] + ); + #endif } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Source/Core/InputCommon/Src/SDL.h b/Source/Core/InputCommon/Src/SDL.h index c3b0597954..b6da81d6cb 100644 --- a/Source/Core/InputCommon/Src/SDL.h +++ b/Source/Core/InputCommon/Src/SDL.h @@ -52,6 +52,13 @@ namespace InputCommon { +////////////////////////////////////////////////////////////////////////////////////////// +// Settings +// ŻŻŻŻŻŻŻŻŻŻ +// Show a status window with the detected axes, buttons and so on +//#define SHOW_PAD_STATUS +////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Structures /* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ @@ -198,7 +205,7 @@ int Pad_Convert(int _val); std::vector Pad_Square_to_Circle(int _x, int _y, int _pad, CONTROLLER_MAPPING _PadMapping); #ifndef _SDL_MAIN_ - + extern int g_LastPad; #endif //////////////////////////// diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp index bd7fe6fb02..e7231db045 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp @@ -63,6 +63,8 @@ void Config::Load(bool ChangePad) iniFile.Get(SectionName.c_str(), "NoTriggerFilter", &bNoTriggerFilter, false); iniFile.Get(SectionName.c_str(), "TriggerType", &Trigger.Type, TRIGGER_OFF); iniFile.Get(SectionName.c_str(), "TriggerRange", &Trigger.Range, 50); + iniFile.Get(SectionName.c_str(), "TriggerRoll", &Trigger.Roll, false); + iniFile.Get(SectionName.c_str(), "TriggerPitch", &Trigger.Pitch, false); // Don't update this when we are loading settings from the ConfigBox if(!ChangePad) @@ -133,6 +135,8 @@ void Config::Save(int Slot) iniFile.Set(SectionName.c_str(), "NoTriggerFilter", bNoTriggerFilter); iniFile.Set(SectionName.c_str(), "TriggerType", Trigger.Type); iniFile.Set(SectionName.c_str(), "TriggerRange", Trigger.Range); + iniFile.Set(SectionName.c_str(), "TriggerRoll", Trigger.Roll); + iniFile.Set(SectionName.c_str(), "TriggerPitch", Trigger.Pitch); // Save the physical device ID number iniFile.Set(SectionName.c_str(), "DeviceID", WiiMoteEmu::PadMapping[i].ID); diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.h b/Source/Plugins/Plugin_Wiimote/Src/Config.h index 264738f017..cee8967188 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.h +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.h @@ -28,6 +28,8 @@ struct Config { int Type; int Range; + int Roll; + int Pitch; }; enum ETriggerType diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp index b0eb4f4eea..eed8bbca5b 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp @@ -585,12 +585,12 @@ void ConfigDialog::PadGetStatus() void ConfigDialog::UpdatePad(wxTimerEvent& WXUNUSED(event)) { // Show the current status - /**/ + /* #ifdef SHOW_PAD_STATUS m_pStatusBar->SetLabel(wxString::Format( "%s", ShowStatus(notebookpage).c_str() )); - #endif + #endif*/ //LogMsg("Abc%s\n", ShowStatus(notebookpage).c_str()); diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp index a06b0ff335..4f0981f3e7 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp @@ -44,59 +44,84 @@ namespace WiiMoteEmu { -void PitchDegreeToAccelerometer(float _Degree, u8 &_y, u8 &_z) +void PitchDegreeToAccelerometer(float _Roll, float _Pitch, u8 &_x, u8 &_y, u8 &_z, bool RollOn, bool PitchOn) { + // Then don't update z either + if (!RollOn && ! PitchOn) return; + // Calculate the radian - float d_rad = _Degree * M_PI / 180.0; + float _RollRad = _Roll * M_PI / 180.0; + float _PitchRad = _Pitch * M_PI / 180.0; // Calculate a good set of y and z values for the degree float r = 1.0; - float fy = r * sin(d_rad); // y - float fz = r * cos(d_rad); // x + float fx = r * sin(_RollRad); // y + float fy = r * sin(_PitchRad); // y + float fz = r * cos(_PitchRad); // x // Multiple with the neutral of z and its g + float xg = g_accel.cal_g.x; float yg = g_accel.cal_g.y; float zg = g_accel.cal_g.z; + float x_zero = g_accel.cal_zero.x; float y_zero = g_accel.cal_zero.y; float z_zero = g_accel.cal_zero.z; + fx = (int) (x_zero + xg * fx); fy = (int) (y_zero + yg * fy); fz = (int) (z_zero + zg * fz); // Boundaries + int ix = (int)fx; int iy = (int)fy; int iz = (int)fz; - if (iy < 0) iy = 0; - if (iy > 255) iy = 255; - _y = iy; + if (ix < 0) ix = 0; if (ix > 255) ix = 255; + if (iy < 0) iy = 0; if (iy > 255) iy = 255; + if (iz < 0) iz = 0; if (iz > 255) iz = 255; + if (RollOn) _x = ix; + if (PitchOn) _y = iy; _z = iz; } - -int PitchAccelerometerToDegree(u8 _y, u8 _z) +// The pitch and roll in 360° +void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch) { /* find out how much it has to move to be 1g */ + float xg = (float)g_accel.cal_g.x; float yg = (float)g_accel.cal_g.y; float zg = (float)g_accel.cal_g.z; - float d = 0; + float Pitch = 0, Roll = 0; /* find out how much it actually moved and normalize to +/- 1g */ + float x = ((float)_x - (float)g_accel.cal_zero.x) / xg; float y = ((float)_y - (float)g_accel.cal_zero.y) / yg; float z = ((float)_z - (float)g_accel.cal_zero.z) / zg; /* make sure x,y,z are between -1 and 1 for the tan function */ + if (x < -1.0) x = -1.0; + else if (x > 1.0) x = 1.0; if (y < -1.0) y = -1.0; else if (y > 1.0) y = 1.0; if (z < -1.0) z = -1.0; else if (z > 1.0) z = 1.0; + // If it is over 1g then it is probably accelerating and may not reliable + //if (abs(accel->x - ac->cal_zero.x) <= ac->cal_g.x) + { + // Calculate the radian + Roll = atan2(x, z); + // Calculate the degree + Roll = (Roll * 180.0) / M_PI; + } + //if (abs(_y - g_accel.cal_zero.y) <= g_accel.cal_g.y) { // Calculate the radian - d = atan2(y, z); + Pitch = atan2(y, z); // Calculate the degree - d = (d * 180.0) / M_PI; + Pitch = (Pitch * 180.0) / M_PI; } - return (int)d; + _Roll = Roll; + _Pitch = Pitch; } -} \ No newline at end of file +} // WiiMoteEmu \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h index 2cfaf5dfc7..da9a89c980 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h @@ -51,8 +51,8 @@ void SetDefaultExtensionRegistry(); // Gamepad bool Search_Devices(std::vector &_joyinfo, int &_NumPads, int &_NumGoodPads); void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONTROLLER_MAPPING_NEW _PadMapping, int controller, int NumButtons); -void PitchDegreeToAccelerometer(float _Degree, u8 &_y, u8 &_z); -int PitchAccelerometerToDegree(u8 _y, u8 _z); +void PitchDegreeToAccelerometer(float _Roll, float _Pitch, u8 &_x, u8 &_y, u8 &_z, bool RollOn, bool PitchOn); +void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch); }; // WiiMoteEmu diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index 59edb02a7a..9c159d6236 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -357,7 +357,7 @@ void SingleShake(u8 &_z, u8 &_y) } else // the default Z if nothing is pressed { - z = Z; + _z = Z; } #endif } @@ -367,7 +367,7 @@ void SingleShake(u8 &_z, u8 &_y) measure of the tilting of the Wiimote. We are interested in this tilting range 90° to -90° */ // --------------- -void TiltWiimoteGamepad(u8 &_y, u8 &_z) +void TiltWiimoteGamepad(u8 &_x, u8 &_y, u8 &_z) { // Return if we have no pads if (NumGoodPads == 0) return; @@ -395,10 +395,8 @@ void TiltWiimoteGamepad(u8 &_y, u8 &_z) } // It's easier to use a float here - float Degree = 0; - // Calculate the present room between the neutral and the maximum values - float RoomAbove = 255.0 - (float)Y; - float RoomBelow = (float)Y; + float Roll = 0; + float Pitch = 0; // Save the Range in degrees, 45° and 90° are good values in some games float Range = (float)g_Config.Trigger.Range; @@ -409,8 +407,8 @@ void TiltWiimoteGamepad(u8 &_y, u8 &_z) Tl = Tl / 2; Tr = Tr / 2; - Degree = Tl * (Range / 128) - - Tr * (Range / 128); + Pitch = Tl * (Range / 128) + - Tr * (Range / 128); } // Analog stick @@ -418,12 +416,14 @@ void TiltWiimoteGamepad(u8 &_y, u8 &_z) { // Adjust the trigger to go between negative and positive values Lx = Lx - 128; + Ly = Ly - 128; // Produce the final value - Degree = -Lx * (Range / 128); + Pitch = -Lx * (Range / 128); + Roll = -Ly * (Range / 128); } - // Calculate the acceleometer value from this tilt angle - PitchDegreeToAccelerometer(Degree, _y, _z); + // Calculate the accelerometer value from this tilt angle + PitchDegreeToAccelerometer(Roll, Pitch, _x, _y, _z, g_Config.Trigger.Roll, g_Config.Trigger.Pitch); //Console::ClearScreen(); /*Console::Print("L:%2.1f R:%2.1f Lx:%2.1f Range:%2.1f Degree:%2.1f L:%i R:%i\n", @@ -476,7 +476,8 @@ void TiltWiimoteKeyboard(u8 &_y, u8 &_z) } else { - PitchDegreeToAccelerometer(KbDegree, _y, _z); + u8 x; + PitchDegreeToAccelerometer(KbDegree, 0, x, _y, _z, false, true); //Console::Print("Degree: %2.1f\n", KbDegree); } // -------------------- @@ -519,6 +520,11 @@ void FillReportAcc(wm_accel& _acc) // ------------------------------------------------ // Wiimote to Gamepad translations // ------------ + + // The following functions may or may not update these values + x = X; + y = Y; + z = Z; // Shake the Wiimote SingleShake(z, y); @@ -527,10 +533,10 @@ void FillReportAcc(wm_accel& _acc) if (g_Config.Trigger.Type == g_Config.KEYBOARD) TiltWiimoteKeyboard(y, z); else if (g_Config.Trigger.Type == g_Config.TRIGGER || g_Config.Trigger.Type == g_Config.ANALOG) - TiltWiimoteGamepad(y, z); + TiltWiimoteGamepad(x, y, z); - // Write values - _acc.x = X; + // Write final values + _acc.x = x; _acc.y = y; _acc.z = z; diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index e4ca419653..6226ac2165 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -626,10 +626,12 @@ void ReadDebugging(bool Emu, const void* _pData, int Size) std::string Tmp2 = TmpData.substr(68, (TmpData.length() - 68)); TmpData = Tmp1 + StringFromFormat("%03i %03i %03i", data[19], data[20], data[21]) + Tmp2; } - // Calculate the Wiimote pitch in degrees - std::string Pitch = StringFromFormat("%i", WiiMoteEmu::PitchAccelerometerToDegree(data[5], data[6])); + // Calculate the Wiimote roll and pitch in degrees + int Roll, Pitch; + WiiMoteEmu::PitchAccelerometerToDegree(data[4], data[5], data[6], Roll, Pitch); + std::string RollPitch = StringFromFormat("%i %i", Roll, Pitch); - Console::Print("Read[%s]: %s| %s\n", (Emu ? "Emu" : "Real"), TmpData.c_str(), Pitch.c_str()); // No timestamp + Console::Print("Read[%s]: %s| %s\n", (Emu ? "Emu" : "Real"), TmpData.c_str(), RollPitch.c_str()); // No timestamp //Console::Print(" (%s): %s\n", Tm(true).c_str(), Temp.c_str()); // Timestamp } if(g_DebugAccelerometer) diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/Config.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/Config.cpp index 7bbd0a8ac8..5b75c43f95 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/Config.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/Config.cpp @@ -136,7 +136,7 @@ void Config::Save(int Slot) { /* Save joypad specific settings. Check for "PadMapping[i].ID < SDL_NumJoysticks()" to avoid reading a joyinfo that does't exist */ - if(PadMapping[i].ID >= SDL_NumJoysticks()) continue; + if(PadMapping[i].ID >= joyinfo.size()) continue; // Create a new section name after the joypad name SectionName = joyinfo[PadMapping[i].ID].Name; @@ -175,7 +175,7 @@ void Config::Save(int Slot) //if(m_frame) m_frame->LogMsg("Saved: %s %i\n", SectionName.c_str(), PadMapping[i].triggertype); } - //Console::Print("%i: Save: %i\n", 0, PadMapping[0].halfpress); + Console::Print("%i: Save: %i\n", 0, PadMapping[0].halfpress); file.Save("nJoy.ini"); } @@ -224,8 +224,8 @@ void Config::Load(bool ChangePad, bool ChangeSaveByID) if(g_Config.bSaveByID) { /* Prevent a crash from illegal access to joyinfo that will only have values for - the current amount of connected PadMapping */ - if(PadMapping[i].ID >= SDL_NumJoysticks()) continue; + the current amount of connected pads */ + if(PadMapping[i].ID >= joyinfo.size()) continue; // Create a section name SectionName = joyinfo[PadMapping[i].ID].Name; @@ -263,6 +263,6 @@ void Config::Load(bool ChangePad, bool ChangeSaveByID) //if(m_frame) m_frame->LogMsg("%i: Enabled: %i\n", i, PadMapping[i].buttons[CTL_X_BUTTON]); } - //Console::Print("%i: Load: %i\n", 0, PadMapping[0].halfpress); + Console::Print("%i: Load: %i\n", 0, PadMapping[0].halfpress); } diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp index 69d56c8701..e5c29e4482 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp @@ -70,11 +70,6 @@ void ConfigBox::PadGetStatus() int PhysicalDevice = PadMapping[notebookpage].ID; int TriggerType = PadMapping[notebookpage].triggertype; - // 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 // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ @@ -220,13 +215,17 @@ std::string ShowStatus(int VirtualController) return StringFromFormat( //"Version: %i.%i.%i\n" + "All pads:\n" "Enabled: %i %i %i %i\n" "ID: %i %i %i %i\n" "Controllertype: %i %i %i %i\n" - "SquareToCircle: %i %i %i %i\n\n" - "Handles: %p %p %p %p\n" + "SquareToCircle: %i %i %i %i\n\n" + #ifdef _WIN32 + "Handles: %i %i %i %i\n" + "XInput: %i %i %i\n" + #endif - "XInput: %i %i %i\n" + "This pad:\n" "Axes: %s\n" "Hats: %s\n" "But: %s\n" @@ -236,10 +235,9 @@ std::string ShowStatus(int VirtualController) PadMapping[0].ID, PadMapping[1].ID, PadMapping[2].ID, PadMapping[3].ID, PadMapping[0].controllertype, PadMapping[1].controllertype, PadMapping[2].controllertype, PadMapping[3].controllertype, PadMapping[0].bSquareToCircle, PadMapping[1].bSquareToCircle, PadMapping[2].bSquareToCircle, PadMapping[3].bSquareToCircle, - joy0, joy1, joy2, joy3, - //PadState[PadMapping[0].ID].joy, PadState[PadMapping[1].ID].joy, PadState[PadMapping[2].ID].joy, PadState[PadMapping[3].ID].joy, - #ifdef _WIN32 + joy0, joy1, joy2, joy3, + //PadState[PadMapping[0].ID].joy, PadState[PadMapping[1].ID].joy, PadState[PadMapping[2].ID].joy, PadState[PadMapping[3].ID].joy, 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(), @@ -251,8 +249,17 @@ std::string ShowStatus(int VirtualController) // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ void ConfigBox::Update() { - // Show the current status - /**/ + // Check that Dolphin is in focus, otherwise don't update the pad status + /* If the emulator is running and unpaused GetJoyState() is run a little more often than needed, + but I allow that since it can confuse the user if the input status in the configuration window + is not update when the emulator is paused. */ + if (g_Config.bCheckFocus || IsFocus()) // && !g_EmulatorRunning) + { + for (int i = 0; i < joyinfo.size(); i++) + InputCommon::GetJoyState(PadState[i], PadMapping[i], i, joyinfo[PadMapping[i].ID].NumButtons); + } + + // Show the current status in a window in the wxPanel #ifdef SHOW_PAD_STATUS m_pStatusBar->SetLabel(wxString::Format( "%s", ShowStatus(notebookpage).c_str() diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp index 076c908267..7b150e9e00 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp @@ -159,10 +159,16 @@ void ConfigBox::OnKeyDown(wxKeyEvent& event) // Close window // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::OnClose(wxCloseEvent& /*event*/) +void ConfigBox::OnClose(wxCloseEvent& event) { - EndModal(0); - if(!g_EmulatorRunning) Shutdown(); // Close pads, unless we are running a game + // Allow wxWidgets to close the window + event.Skip(); + + // Stop the timer + m_ConstantTimer->Stop(); + + // Close pads, unless we are running a game + if(!g_EmulatorRunning) Shutdown(); } // Call about dialog @@ -977,9 +983,9 @@ void ConfigBox::CreateGUIControls() // Don't allow these changes when running if(g_EmulatorRunning) { - m_Joyname[i]->Enable(false); + //m_Joyname[i]->Enable(false); m_Joyattach[i]->Enable(false); - m_ControlType[i]->Enable(false); + //m_ControlType[i]->Enable(false); } // Update GUI diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp index 7853dfafbb..43e1724f0d 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp @@ -88,8 +88,10 @@ 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 +int NumPads = 0, NumGoodPads = 0, LastPad = 0; +#ifdef _WIN32 + HWND m_hWnd = NULL, m_hConsole = NULL; // Handle to window +#endif SPADInitialize *g_PADInitialize = NULL; // TODO: fix this dirty hack to stop missing symbols @@ -187,28 +189,28 @@ void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals) {} void DllConfig(HWND _hParent) { // Debugging - //Console::Open(); + #ifdef SHOW_PAD_STATUS + Console::Open(100); + m_hConsole = Console::GetHwnd(); + #endif #ifdef _WIN32 // Start the pads so we can use them in the configuration and advanced controls if(!g_EmulatorRunning) { Search_Devices(joyinfo, NumPads, NumGoodPads); // Populate joyinfo for all attached devices + + // Check if a DirectInput error occured + if(ReloadDLL()) + { + PostMessage(_hParent, WM_USER, NJOY_RELOAD, 0); + return; + } } m_frame = new ConfigBox(NULL); - m_frame->ShowModal(); + m_frame->Show(); - /* 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 */ - if ( (PadMapping[0].enabled && PadState[0].joy == NULL) - || (PadMapping[1].enabled && PadState[1].joy == NULL) - || (PadMapping[2].enabled && PadState[2].joy == NULL) - || (PadMapping[3].enabled && PadState[3].joy == NULL)) - { - //PostMessage(_hParent, 25, 0, 0); - Console::Print("%s\n", SDL_GetError()); - } #else if (SDL_Init(SDL_INIT_JOYSTICK ) < 0) { @@ -238,7 +240,10 @@ void DllDebugger(HWND _hParent, bool Show) {} void Initialize(void *init) { // Debugging - //Console::Open(); + #ifdef SHOW_PAD_STATUS + Console::Open(100); + m_hConsole = Console::GetHwnd(); + #endif Console::Print("Initialize: %i\n", SDL_WasInit(0)); g_PADInitialize = (SPADInitialize*)init; g_EmulatorRunning = true; @@ -251,18 +256,11 @@ void Initialize(void *init) m_hWnd = (HWND)g_PADInitialize->hWnd; #endif - Search_Devices(joyinfo, NumPads, NumGoodPads); // Populate joyinfo for all attached devices + // Populate joyinfo for all attached devices if the configuration window is not already open + if(!m_frame) Search_Devices(joyinfo, NumPads, NumGoodPads); - /* 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 */ - if ( (PadMapping[0].enabled && PadState[0].joy == NULL) - || (PadMapping[1].enabled && PadState[1].joy == NULL) - || (PadMapping[2].enabled && PadState[2].joy == NULL) - || (PadMapping[3].enabled && PadState[3].joy == NULL)) - { - g_PADInitialize->padNumber = -1; - Console::Print("%s\n", SDL_GetError()); - } + // Check if a DirectInput error occured + if(ReloadDLL()) g_PADInitialize->padNumber = -1; } bool Search_Devices(std::vector &_joyinfo, int &_NumPads, int &_NumGoodPads) @@ -299,27 +297,40 @@ void Shutdown() { Console::Print("Shutdown: %i\n", SDL_WasInit(0)); + // Always change this variable + g_EmulatorRunning = false; + + // Don't shutdown if the configuration window is still showing + if (m_frame) return; + /* Close all devices carefully. We must check that we are not accessing any undefined vector elements or any bad devices */ for (int i = 0; i < 4; i++) { if (PadMapping[i].enabled && joyinfo.size() > PadMapping[i].ID) if (joyinfo.at(PadMapping[i].ID).Good) - if(SDL_JoystickOpened(PadMapping[i].ID)) SDL_JoystickClose(PadState[i].joy); + if(SDL_JoystickOpened(PadMapping[i].ID)) + { + SDL_JoystickClose(PadState[i].joy); + PadState[i].joy = NULL; + } } // Clear the physical device info joyinfo.clear(); + NumPads = 0; + NumGoodPads = 0; // Finally close SDL if (SDL_WasInit(0)) SDL_Quit(); + // Remove the pointer to the initialize data + g_PADInitialize = NULL; + #ifdef _DEBUG DEBUG_QUIT(); #endif - g_EmulatorRunning = false; - #ifdef _WIN32 #ifdef USE_RUMBLE_DINPUT_HACK FreeDirectInput(); @@ -376,7 +387,7 @@ unsigned int PAD_GetAttachedPads() if (PadMapping[2].enabled) connected |= 4; if (PadMapping[3].enabled) connected |= 8; - //Console::Print("PAD_GetAttachedPads: %i %i %i\n", PadMapping[0].enabled, PadMapping[1].enabled, PadMapping[2].enabled, PadMapping[3].enabled); + //Console::Print("PAD_GetAttachedPads: %i %i %i %i\n", PadMapping[0].enabled, PadMapping[1].enabled, PadMapping[2].enabled, PadMapping[3].enabled); return connected; } @@ -388,16 +399,17 @@ unsigned int PAD_GetAttachedPads() // Function: Gives the current pad status to the Core void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) { - //Console::Print("%i %i %i\n", _numPAD, PadMapping[_numPAD].enabled, PadState[_numPAD].joy); + //Console::Print("PAD_GetStatus(): %i %i %i\n", _numPAD, PadMapping[_numPAD].enabled, PadState[_numPAD].joy); - // Check if the pad is enabled + /* Check if the pad is enabled and avaliable, currently we don't disable pads just because they are + disconnected */ if (!PadMapping[_numPAD].enabled || !PadState[_numPAD].joy) return; // Clear pad status memset(_pPADStatus, 0, sizeof(SPADStatus)); // Check that Dolphin is in focus, otherwise don't update the pad status - if (!g_Config.bCheckFocus && IsFocus()) + if (g_Config.bCheckFocus || IsFocus()) GetJoyState(PadState[_numPAD], PadMapping[_numPAD], _numPAD, joyinfo[PadMapping[_numPAD].ID].NumButtons); // Get type @@ -525,53 +537,81 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) // Use rumble Pad_Use_Rumble(_numPAD, _pPADStatus); - /* Debugging - if(_numPAD == 1) - { - Console::ClearScreen(); - Console::Print( - "Pad %i: %i %i\n" - "State: L:%i R:%i HalfPress:%i\n" - "Trigger type: %s StatusLeft:%04x StatusRight:%04x TriggerLeft:%04x TriggerRight:%04x TriggerValue:%i\n" - "Buttons: %i X:%i\n" - "D-Pad type: %s L:%i R:%i U:%i D:%i", + // Debugging + /* + // Show the status of all connected pads + if ((LastPad == 0 && _numPAD == 0) || _numPAD < LastPad) Console::ClearScreen(); + LastPad = _numPAD; + Console::Print( + "Pad | Number:%i Enabled:%i Handle:%i\n" + "Trigger | StatusLeft:%04x StatusRight:%04x TriggerLeft:%04x TriggerRight:%04x TriggerValue:%i\n" + "Buttons | Overall:%i X:%i\n" + "======================================================\n", - _numPAD, PadMapping[_numPAD].enabled, PadState[_numPAD].joy, + _numPAD, PadMapping[_numPAD].enabled, PadState[_numPAD].joy, - PadState[_numPAD].buttons[CTL_L_SHOULDER], PadState[_numPAD].buttons[CTL_R_SHOULDER], PadState[_numPAD].halfpress, + PadState[_numPAD].buttons[InputCommon::CTL_L_SHOULDER], PadState[_numPAD].buttons[InputCommon::CTL_R_SHOULDER], PadState[_numPAD].halfpress, - (PadMapping[_numPAD].triggertype ? "CTL_TRIGGER_XINPUT" : "CTL_TRIGGER_SDL"), - _pPADStatus->triggerLeft, _pPADStatus->triggerRight, TriggerLeft, TriggerRight, TriggerValue, + (PadMapping[_numPAD].triggertype ? "CTL_TRIGGER_XINPUT" : "CTL_TRIGGER_SDL"), + _pPADStatus->triggerLeft, _pPADStatus->triggerRight, TriggerLeft, TriggerRight, TriggerValue, - _pPADStatus->button, PadState[_numPAD].buttons[CTL_X_BUTTON], - - (PadMapping[_numPAD].controllertype ? "CTL_DPAD_CUSTOM" : "CTL_DPAD_HAT"), - 0, 0, 0, 0 - ); - }*/ + _pPADStatus->button, PadState[_numPAD].buttons[InputCommon::CTL_X_BUTTON] + ); + */ } ///////////////////////////////////////////////// Spec functions - //****************************************************************************** // Supporting functions //****************************************************************************** +////////////////////////////////////////////////////////////////////////////////////////// +/* Check if any of the pads failed to open. In Windows there is a strange "IDirectInputDevice2:: + SetDataFormat() DirectX error -2147024809" after exactly four SDL_Init() and SDL_Quit() */ +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +bool ReloadDLL() +{ + if ( (PadMapping[0].enabled && PadState[0].joy == NULL) + || (PadMapping[1].enabled && PadState[1].joy == NULL) + || (PadMapping[2].enabled && PadState[2].joy == NULL) + || (PadMapping[3].enabled && PadState[3].joy == NULL)) + { + // Check if it was an error and not just no pads connected + std::string StrError = SDL_GetError(); + if (StrError.find("IDirectInputDevice2") != std::string::npos) + { + // Clear the physical device info + joyinfo.clear(); + NumPads = 0; + NumGoodPads = 0; + // Close SDL + if (SDL_WasInit(0)) SDL_Quit(); + // Log message + Console::Print("Error: %s\n", StrError.c_str()); + return true; + } + } + + return false; +} + ////////////////////////////////////////////////////////////////////////////////////////// // Check if Dolphin is in focus // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ bool IsFocus() { +return true; + #ifdef _WIN32 HWND RenderingWindow = NULL; if (g_PADInitialize) RenderingWindow = g_PADInitialize->hWnd; HWND Parent = GetParent(RenderingWindow); HWND TopLevel = GetParent(Parent); HWND Config = NULL; if (m_frame) Config = (HWND)m_frame->GetHWND(); - // Support both rendering to main window and not - if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == RenderingWindow || GetForegroundWindow() == Config) + // Support both rendering to main window and not, and the config and eventual console window + if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == RenderingWindow || GetForegroundWindow() == Config || GetForegroundWindow() == m_hConsole) return true; else return false; diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h index 669d7907e4..ed4d6e3387 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h @@ -30,14 +30,15 @@ ////////////////////////////////////////////////////////////////////////////////////////// +#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 - -// Show a status window with the detected axes, buttons and so on -//#define SHOW_PAD_STATUS ////////////////////////// @@ -125,8 +126,10 @@ extern std::vector Keys; 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 + #ifdef _WIN32 + extern HWND m_hWnd, m_hConsole; // Handle to window + #endif + extern int NumPads, NumGoodPads, LastPad; // Number of goods pads #endif @@ -137,8 +140,12 @@ bool Search_Devices(std::vector &_joyinfo, int &_N void DEBUG_INIT(); void DEBUG_QUIT(); bool IsFocus(); +bool ReloadDLL(); void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus); // Rumble //void SaveConfig(); //void LoadConfig(); + + +#endif __NJOY_h__ \ No newline at end of file