diff --git a/Source/Core/InputCommon/InputCommon.vcproj b/Source/Core/InputCommon/InputCommon.vcproj index f143a36dfb..9693fa9d25 100644 --- a/Source/Core/InputCommon/InputCommon.vcproj +++ b/Source/Core/InputCommon/InputCommon.vcproj @@ -415,10 +415,6 @@ RelativePath=".\Src\Configuration.cpp" > - - diff --git a/Source/Core/InputCommon/Src/Configuration.cpp b/Source/Core/InputCommon/Src/Configuration.cpp index e69de29bb2..44b5c05555 100644 --- a/Source/Core/InputCommon/Src/Configuration.cpp +++ b/Source/Core/InputCommon/Src/Configuration.cpp @@ -0,0 +1,155 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// Project description +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// Name: Input Configuration and Calibration +// Description: Common SDL Input Functions +// +// Author: Falcon4ever (nJoy@falcon4ever.com, www.multigesture.net), JPeterson etc +// Copyright (C) 2003-2008 Dolphin Project. +// +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////////////////////////////// +// Include +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +#include "SDL.h" // Local +//////////////////////////////////// + + +namespace InputCommon +{ + + +////////////////////////////////////////////////////////////////////////////////////////// +// 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, CONTROLLER_MAPPING _PadMapping) +{ + /* 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.SDiagonal.substr(0, _PadMapping.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; +} +///////////////////////////////////////////////////////////////////// + + +} \ No newline at end of file diff --git a/Source/Core/InputCommon/Src/Configuration.h b/Source/Core/InputCommon/Src/Configuration.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Source/Core/InputCommon/Src/SDL.h b/Source/Core/InputCommon/Src/SDL.h index a6747f8aaf..02305df771 100644 --- a/Source/Core/InputCommon/Src/SDL.h +++ b/Source/Core/InputCommon/Src/SDL.h @@ -36,6 +36,7 @@ // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ #include // System #include +#include #include // Externals @@ -153,9 +154,15 @@ enum ////////////////////////////////////////////////////////////////////////////////////////// // Declarations // ŻŻŻŻŻŻŻŻŻ + +// General functions bool SearchDevices(std::vector &_joyinfo, int &NumPads, int &NumGoodPads); void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int controller, int NumButtons); +// Value conversion +int Pad_Convert(int _val); +std::vector Pad_Square_to_Circle(int _x, int _y, int _pad, CONTROLLER_MAPPING _PadMapping); + #ifndef _SDL_MAIN_ #endif diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp index b2f2d8bdb6..bffb715001 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp @@ -92,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); } @@ -146,8 +146,8 @@ void ConfigBox::PadGetStatus() // Convert the triggers values 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 diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp index 185df15abc..9f6c15e03b 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp @@ -419,22 +419,22 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) // 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 == InputCommon::CTL_TRIGGER_SDL) { - if(PadMapping[_numPAD].buttons[InputCommon::CTL_L_SHOULDER] >= 1000) TriggerLeft = Pad_Convert(TriggerLeft); - if(PadMapping[_numPAD].buttons[InputCommon::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?) @@ -582,115 +582,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 diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h index 556bfc6f28..8377b5c003 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h @@ -136,8 +136,6 @@ 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();