Wiimote and nJoy > Gamepad changes

1. Added LiveUpdates, while the configuration window is open nJoy and Wiimote will check for connected/disconnected pads
2. Removed the 'Nintendo RVL-CNT-01' device from the device list, and other SDL devices with no axes/buttons
3. Added SDL (from the current SVN) to get debugging information for SDL.dll
4. Added 'Upright Wiimote' option to emulated Wiimote options

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4534 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson
2009-11-12 18:57:35 +00:00
parent b858befba2
commit 71506bc0f7
590 changed files with 197210 additions and 17135 deletions
@@ -251,6 +251,12 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool
#endif
}
void ConsoleListener::CustomLog(const char *Text)
{
DWORD cCharsWritten;
WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL);
}
void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
{
#if defined(_WIN32)
+1
View File
@@ -83,6 +83,7 @@ public:
#ifdef _WIN32
COORD GetCoordinates(int BytesRead, int BufferWidth);
#endif
void CustomLog(const char *Text);
void Log(LogTypes::LOG_LEVELS, const char *Text);
void ClearScreen(bool Cursor = true);
+7 -7
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="Dolphin"
ProjectGUID="{A72606EF-C5C1-4954-90AD-F0F93A8D97D9}"
RootNamespace="DolphinWX"
@@ -91,7 +91,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib rpcrt4.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib wxmsw28u_adv.lib wxmsw28u_aui.lib Bochs_disasm.lib LZO.lib SFML_Network.lib zlib.lib"
OutputFile="../../../Binary/Win32/Dolphin.exe"
OutputFile="../../../Binary/$(PlatformName)/Dolphin.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="$(SolutionDir)\$(ConfigurationName)\$(PlatformName);..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)"
@@ -208,13 +208,13 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib rpcrt4.lib wxbase28u.lib wxmsw28u_core.lib wxmsw28u_adv.lib wxmsw28u_aui.lib"
OutputFile="../../../Binary/x64/Dolphin.exe"
OutputFile="../../../Binary/$(PlatformName)/Dolphin.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="$(SolutionDir)\$(ConfigurationName)\$(PlatformName);..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)"
IgnoreAllDefaultLibraries="false"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="true"
GenerateDebugInformation="false"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
BaseAddress="0x00400000"
@@ -546,7 +546,7 @@
Name="VCLinkerTool"
AdditionalOptions="/NODEFAULTLIB:msvcrt.lib&#x0D;&#x0A;/NODEFAULTLIB:libcmtd.lib"
AdditionalDependencies="comctl32.lib rpcrt4.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib wxmsw28u_adv.lib wxmsw28u_aui.lib Bochs_disasm.lib LZO.lib SFML_Network.lib zlib.lib"
OutputFile="../../../Binary/Win32/DolphinDF.exe"
OutputFile="&quot;$(SolutionDir)/../../../Binary/$(PlatformName)/DolphinDF.exe&quot;"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="&quot;$(SolutionDir)\Release\$(PlatformName)&quot;;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;"
@@ -659,7 +659,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib rpcrt4.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib wxmsw28u_adv.lib wxmsw28u_aui.lib Bochs_disasm.lib LZO.lib SFML_Network.lib zlib.lib"
OutputFile="../../../Binary/x64/DolphinDF.exe"
OutputFile="../../../Binary/$(PlatformName)/DolphinDF.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="&quot;$(SolutionDir)\Release\$(PlatformName)&quot;;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;"
@@ -773,7 +773,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib rpcrt4.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib wxmsw28u_adv.lib wxmsw28u_aui.lib Bochs_disasm.lib LZO.lib SFML_Network.lib zlib.lib"
OutputFile="../../../Binary/Win32/DolphinIL.exe"
OutputFile="../../../Binary/$(PlatformName)/DolphinIL.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="&quot;$(SolutionDir)\Release\$(PlatformName)&quot;;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;"
+7 -1
View File
@@ -127,6 +127,12 @@ void CFrame::ToggleConsole(bool bShow, int i)
#ifdef _WIN32
ConsoleListener *Console = LogManager::GetInstance()->getConsoleListener();
// For developers: Use this to get a regular separate console window
/*
if(!GetConsoleWindow()) Console->Open(); else ShowWindow(GetConsoleWindow(), SW_SHOW);
return;
*/
if (bShow)
{
//Console->Log(LogTypes::LNOTICE, StringFromFormat(" >>> Show\n").c_str());
@@ -748,7 +754,7 @@ void CFrame::ResizeConsole()
wxBorder = 2;
Border = 4;
LowerBorder = 6;
MenuBar = 30; // Including upper border
MenuBar = 26; // Including upper border
ScrollBar = 19;
}
else // XP
+4 -3
View File
@@ -234,7 +234,7 @@ void CLogWindow::OnClear(wxCommandEvent& WXUNUSED (event))
for (int i = 0; i < msgQueueSize; i++)
msgQueue.pop();
m_LogSection.Leave();
m_console->ClearScreen();
NOTICE_LOG(CONSOLE, "Console cleared");
NotifyUpdate();
@@ -517,11 +517,12 @@ void CLogWindow::UpdateLog()
m_LogTimer->Start(UPDATETIME);
}
// Receive log messages
void CLogWindow::Log(LogTypes::LOG_LEVELS level, const char *text)
{
m_LogSection.Enter();
if (msgQueue.size() >= 100)
msgQueue.pop();
// Remove the first message if the queue is big
//if (msgQueue.size() >= 200) msgQueue.pop();
msgQueue.push(std::pair<u8, wxString>((u8)level, wxString::FromAscii(text)));
m_LogSection.Leave();
}
+221 -35
View File
@@ -35,46 +35,63 @@
#define _SDL_MAIN_ // Avoid certain declarations in SDL.h
#include "SDL.h" // Local
#include "XInput.h"
#ifdef _WIN32
#include <windows.h>
#include <dinput.h>
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dinput8.lib")
#endif
// Definitions
// -------------------
int g_LastPad = 0;
namespace InputCommon
{
// Definitions
// -------------------
int g_LastPad = 0;
int NumDIDevices = 0;
// Search attached devices. Populate joyinfo for all attached physical devices.
// Reset and search for devices
// -----------------------
bool SearchDevices(std::vector<CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
bool SearchDevicesReset(std::vector<CONTROLLER_INFO> &_joyinfo, int &_NumPads)
{
// This is needed to update SDL_NumJoysticks
if (SDL_WasInit(0))
SDL_Quit();
return SearchDevices(_joyinfo, _NumPads);
}
// Initialize if not previously initialized
// -----------------------
bool SearchDevices(std::vector<CONTROLLER_INFO> &_joyinfo, int &_NumPads)
{
// Init Joystick + Haptic (force feedback) subsystem on SDL 1.3
if (!SDL_WasInit(0))
#if SDL_VERSION_ATLEAST(1, 3, 0)
{
#if SDL_VERSION_ATLEAST(1, 3, 0) && !defined(_WIN32)
NOTICE_LOG(PAD, "SDL_Init | HAPTIC");
if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC) < 0)
#else
//NOTICE_LOG(PAD, "SDL_Init");
if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
#endif
{
PanicAlert("Could not initialize SDL: %s", SDL_GetError());
return false;
}
}
// Clear joyinfo
_joyinfo.clear();
// Get device status
int numjoy = SDL_NumJoysticks();
for (int i = 0; i < numjoy; i++ )
{
{
CONTROLLER_INFO Tmp;
Tmp.joy = SDL_JoystickOpen(i);
@@ -86,39 +103,160 @@ bool SearchDevices(std::vector<CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_
Tmp.Name = SDL_JoystickName(i);
// Check if the device is okay
if ( Tmp.NumAxes == 0
if ( !( Tmp.NumAxes == 0
&& Tmp.NumBalls == 0
&& Tmp.NumButtons == 0
&& Tmp.NumHats == 0
&& Tmp.NumHats == 0)
)
{
Tmp.Good = false;
_joyinfo.push_back(Tmp);
}
else
{
_NumGoodPads++;
Tmp.Good = true;
}
_joyinfo.push_back(Tmp);
// We have now read the values we need so we close the device
if (SDL_JoystickOpened(i)) SDL_JoystickClose(_joyinfo[i].joy);
//if (SDL_JoystickOpened(i)) SDL_JoystickClose(Tmp.joy);
}
}
_NumPads = (int)_joyinfo.size();
return true;
}
// Show the current pad status
// -----------------
std::string ShowStatus(int Slot, int Device, CONTROLLER_MAPPING PadMapping[], CONTROLLER_STATE PadState[],
std::vector<InputCommon::CONTROLLER_INFO> joyinfo)
{
CONTROLLER_MAPPING_NEW _PadMapping[4];
CONTROLLER_STATE_NEW _PadState[4];
for (int i = 0; i < 4; i++)
{
_PadMapping[i].ID = PadMapping[i].ID;
_PadMapping[i].Name = PadMapping[i].Name;
_PadState[i].joy = PadState[i].joy;
}
return DoShowStatus(Slot, Device, _PadMapping, _PadState, joyinfo);
}
std::string DoShowStatus(int Slot, int Device,
CONTROLLER_MAPPING_NEW PadMapping[], CONTROLLER_STATE_NEW PadState[],
std::vector<InputCommon::CONTROLLER_INFO> joyinfo)
{
// Save the physical device
int ID = PadMapping[Slot].ID;
// Make local shortcut
SDL_Joystick *joy = PadState[Slot].joy;
// Make shortcuts for all pads
SDL_Joystick *joy0 = PadState[0].joy;
SDL_Joystick *joy1 = PadState[1].joy;
SDL_Joystick *joy2 = PadState[2].joy;
SDL_Joystick *joy3 = PadState[3].joy;
// Temporary storage
std::string
StrAllHandles, StrAllName,
StrHandles, StrId, StrName,
StrAxes, StrHats, StrBut;
int value;
// All devices
int numjoy = SDL_NumJoysticks();
for (int i = 0; i < numjoy; i++ )
{
SDL_Joystick *AllJoy = SDL_JoystickOpen(i);
StrAllHandles += StringFromFormat(" %i:%06i", i, AllJoy);
StrAllName += StringFromFormat("Name %i: %s\n", i, SDL_JoystickName(i));
}
// Get handles
for(int i = 0; i < joyinfo.size(); i++)
{
StrHandles += StringFromFormat(" %i:%06i", i, joyinfo.at(i).joy);
StrId += StringFromFormat(" %i:%i", i, joyinfo.at(i).ID);
StrName += StringFromFormat("Name %i:%s\n", i, joyinfo.at(i).Name.c_str());
}
// Get status
int Axes = joyinfo[Device].NumAxes;
int Balls = joyinfo[Device].NumBalls;
int Hats = joyinfo[Device].NumHats;
int Buttons = joyinfo[Device].NumButtons;
// Update the internal values
SDL_JoystickUpdate();
// Go through all axes and read out their values
for(int i = 0; i < Axes; i++)
{
value = SDL_JoystickGetAxis(joy, i);
StrAxes += StringFromFormat(" %i:%06i", i, value);
}
for(int i = 0;i < Hats; i++)
{
value = SDL_JoystickGetHat(joy, i);
StrHats += StringFromFormat(" %i:%i", i, value);
}
for(int i = 0;i < Buttons; i++)
{
value = SDL_JoystickGetButton(joy, i);
StrBut += StringFromFormat(" %i:%i", i+1, value);
}
return StringFromFormat(
"All devices:\n"
"Handles: %s\n"
"%s"
"\nAll pads:\n"
"Handles: %s\n"
"ID: %s\n"
"%s"
"\nAll slots:\n"
"ID: %i %i %i %i\n"
"Name: '%s' '%s' '%s' '%s'\n"
//"Controllertype: %i %i %i %i\n"
//"SquareToCircle: %i %i %i %i\n\n"
#ifdef _WIN32
"Handles: %i %i %i %i\n"
//"XInput: %i %i %i\n"
#endif
"\nThis pad:\n"
"Handle: %06i\n"
"ID: %i\n"
//"Slot: %i\n"
"Axes: %s\n"
"Hats: %s\n"
"But: %s\n"
"Device: Ax: %i Balls:%i Hats:%i But:%i",
StrAllHandles.c_str(), StrAllName.c_str(),
StrHandles.c_str(), StrId.c_str(), StrName.c_str(),
PadMapping[0].ID, PadMapping[1].ID, PadMapping[2].ID, PadMapping[3].ID,
PadMapping[0].Name.c_str(), PadMapping[1].Name.c_str(), PadMapping[2].Name.c_str(), PadMapping[3].Name.c_str(),
//PadMapping[0].controllertype, PadMapping[1].controllertype, PadMapping[2].controllertype, PadMapping[3].controllertype,
//PadMapping[0].bSquareToCircle, PadMapping[1].bSquareToCircle, PadMapping[2].bSquareToCircle, PadMapping[3].bSquareToCircle,
#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),
joy,
#endif
//Slot,
ID,
StrAxes.c_str(), StrHats.c_str(), StrBut.c_str(),
Axes, Balls, Hats, Buttons
);
}
// 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) */
@@ -140,10 +278,15 @@ 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)
{
if (SDL_JoystickEventState(SDL_QUERY) == SDL_ENABLE) return;
//NOTICE_LOG(PAD, "SDL_JoystickEventState: %s", (SDL_JoystickEventState(SDL_QUERY) == SDL_ENABLE) ? "SDL_ENABLE" : "SDL_IGNORE");
// Update the gamepad status
SDL_JoystickUpdate();
// Read info
int NumButtons = SDL_JoystickNumButtons(_PadState.joy);
// Update axis states. It doesn't hurt much if we happen to ask for nonexisting axises here.
_PadState.axis[CTL_MAIN_X] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_MAIN_X]);
@@ -206,12 +349,13 @@ void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, in
}
#ifdef SHOW_PAD_STATUS
/*
// Show the status of all connected pads
//ConsoleListener* Console = LogManager::GetInstance()->getConsoleListener();
//if ((g_LastPad == 0 && Controller == 0) || Controller < g_LastPad) Console->ClearScreen();
//if ((g_LastPad == 0 && _PadMapping.ID == 0) || Controller < g_LastPad) Console->ClearScreen();
g_LastPad = Controller;
NOTICE_LOG(CONSOLE,
"Pad | Number:%i Enabled:%i Handle:%i\n"
"Pad | Number:%i Handle:%i\n"
"Main Stick | X:%03i Y:%03i\n"
"C Stick | X:%03i Y:%03i\n"
"Trigger | Type:%s DigitalL:%i DigitalR:%i AnalogL:%03i AnalogR:%03i HalfPress:%i\n"
@@ -219,7 +363,7 @@ void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, in
"D-Pad | Type:%s Hat:%i U:%i D:%i\n"
"======================================================\n",
Controller, _PadMapping.enabled, _PadState.joy,
_PadMapping.ID, _PadState.joy,
_PadState.axis[InputCommon::CTL_MAIN_X], _PadState.axis[InputCommon::CTL_MAIN_Y],
_PadState.axis[InputCommon::CTL_SUB_X], _PadState.axis[InputCommon::CTL_SUB_Y],
@@ -235,6 +379,7 @@ void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, in
_PadState.dpad,
_PadState.dpad2[InputCommon::CTL_D_PAD_UP], _PadState.dpad2[InputCommon::CTL_D_PAD_DOWN]
);
*/
#endif
}
@@ -263,18 +408,23 @@ bool AvoidValues(int value, bool NoTriggerFilter)
// Detect a pressed button
// ---------------------
void GetButton(SDL_Joystick *joy, int ControllerID, int buttons, int axes, int hats,
void GetButton(SDL_Joystick *joy, int ControllerID,
int &KeyboardKey, int &value, int &type, int &pressed, bool &Succeed, bool &Stop,
bool LeftRight, bool Axis, bool XInput, bool Button, bool Hat, bool NoTriggerFilter)
{
// It needs the wxWidgets excape keycode
static const int WXK_ESCAPE = 27;
// Save info
int buttons = SDL_JoystickNumButtons(joy);
int axes = SDL_JoystickNumAxes(joy);;
int hats = SDL_JoystickNumHats(joy);;
// Update the internal status
SDL_JoystickUpdate();
// For the triggers we accept both a digital or an analog button
if(Axis)
if (Axis)
{
for(int i = 0; i < axes; i++)
{
@@ -289,7 +439,7 @@ void GetButton(SDL_Joystick *joy, int ControllerID, int buttons, int axes, int h
}
// Check for a hat
if(Hat)
if (Hat)
{
for(int i = 0; i < hats; i++)
{
@@ -370,5 +520,41 @@ void GetButton(SDL_Joystick *joy, int ControllerID, int buttons, int axes, int h
// **********************************************
// Search for DirectInput devices
// ----------------
#ifdef _WIN32
BOOL CALLBACK EnumDICallback(const DIDEVICEINSTANCE* pInst, VOID* pContext)
{
NumDIDevices++;
return true;
}
#endif
int SearchDIDevices()
{
#ifdef _WIN32
LPDIRECTINPUT8 g_pObject;
LPDIRECTINPUTDEVICE8 g_pDevice;
DIPROPDWORD dipdw;
HRESULT hr;
NumDIDevices = 0;
// Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use.
if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_pObject, NULL)))
return 0;
// Look for a device
if (FAILED(hr = g_pObject->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumDICallback, NULL, DIEDFL_ATTACHEDONLY)))
return 0;
return NumDIDevices;
#else
return 0;
#endif
}
} // InputCommon
+16 -8
View File
@@ -53,7 +53,7 @@
#endif
#include "Common.h" // Common
#include "StringUtil.h"
namespace InputCommon
@@ -62,7 +62,7 @@ namespace InputCommon
// Settings
// ----------
// Show a status window with the detected axes, buttons and so on
// Show a status window with the detected devices etc
//#define SHOW_PAD_STATUS
@@ -82,7 +82,7 @@ struct CONTROLLER_STATE // GC PAD INFO/STATE
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 ;)...
int halfpress; // L and R triggers half pressed
SDL_Joystick *joy; // SDL joystick device
};
@@ -95,6 +95,7 @@ struct CONTROLLER_MAPPING // GC PAD MAPPING
int halfpress; // (See above)
int deadzone; // Deadzone... what else?
int ID; // SDL joystick device ID
std::string Name; // SDL joystick device name
int controllertype; // Hat: Hat or custom buttons
int triggertype; // Triggers range
std::string SRadius, SDiagonal, SRadiusC, SDiagonalC;
@@ -111,7 +112,6 @@ struct CONTROLLER_INFO // CONNECTED WINDOWS DEVICES INFO
int NumHats; // Amount of Hats (POV)
std::string Name; // Joypad/stickname
int ID; // SDL joystick device ID
bool Good; // Pad is good (it has at least one button or axis)
SDL_Joystick *joy; // SDL joystick device
};
enum
@@ -220,6 +220,7 @@ struct CONTROLLER_MAPPING_NEW // GC PAD MAPPING
int DeadZoneL; // Analog 1 Deadzone
int DeadZoneR; // Analog 2 Deadzone
int ID; // SDL joystick device ID
std::string Name; // SDL joystick device name
int controllertype; // D-Pad type: Hat or custom buttons
int triggertype; // SDL or XInput trigger
std::string SDiagonal;
@@ -236,9 +237,14 @@ struct CONTROLLER_MAPPING_NEW // GC PAD MAPPING
// ---------
// General functions
bool SearchDevices(std::vector<CONTROLLER_INFO> &_joyinfo, int &NumPads, int &NumGoodPads);
void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int controller, int NumButtons);
void GetButton(SDL_Joystick*, int,int,int,int, int&,int&,int&,int&,bool&,bool&, bool,bool,bool,bool,bool,bool);
bool SearchDevicesReset(std::vector<CONTROLLER_INFO> &_joyinfo, int &NumPads);
bool SearchDevices(std::vector<CONTROLLER_INFO> &_joyinfo, int &NumPads);
std::string ShowStatus(int Slot, int Device, CONTROLLER_MAPPING PadMapping[], CONTROLLER_STATE PadState[],
std::vector<InputCommon::CONTROLLER_INFO> joyinfo);
std::string DoShowStatus(int Slot, int Device, CONTROLLER_MAPPING_NEW PadMapping[], CONTROLLER_STATE_NEW PadState[],
std::vector<InputCommon::CONTROLLER_INFO> joyinfo);
void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping);
void GetButton(SDL_Joystick*, int, int&,int&,int&,int&,bool&,bool&, bool,bool,bool,bool,bool,bool);
// Value conversion
float Deg2Rad(float Deg);
@@ -256,7 +262,9 @@ std::string VKToString(int keycode);
extern int g_LastPad;
#endif
// DirectInput
extern int NumDIDevices;
int SearchDIDevices();
} // InputCommon
+19
View File
@@ -95,6 +95,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_nJoy_SDL", "Plugins\
ProjectSection(ProjectDependencies) = postProject
{C7E5D50A-2916-464B-86A7-E10B3CC88ADA} = {C7E5D50A-2916-464B-86A7-E10B3CC88ADA}
{11F55366-12EC-4C44-A8CB-1D4E315D61ED} = {11F55366-12EC-4C44-A8CB-1D4E315D61ED}
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68} = {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}
EndProjectSection
EndProject
@@ -114,6 +115,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_Wiimote", "Plugins\P
ProjectSection(ProjectDependencies) = postProject
{C7E5D50A-2916-464B-86A7-E10B3CC88ADA} = {C7E5D50A-2916-464B-86A7-E10B3CC88ADA}
{11F55366-12EC-4C44-A8CB-1D4E315D61ED} = {11F55366-12EC-4C44-A8CB-1D4E315D61ED}
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68} = {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}
{0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E} = {0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E}
{1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE} = {1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE}
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}
@@ -199,6 +201,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_VideoSoftware", "Plu
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL", "..\Externals\SDL\VisualC\SDL\SDL_VS2008.vcproj", "{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -696,6 +700,21 @@ Global
{66A4E7BD-E2E8-4373-9B75-8750EB5AE683}.Release|Win32.Build.0 = Release|Win32
{66A4E7BD-E2E8-4373-9B75-8750EB5AE683}.Release|x64.ActiveCfg = Release|x64
{66A4E7BD-E2E8-4373-9B75-8750EB5AE683}.Release|x64.Build.0 = Release|x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Win32.ActiveCfg = Debug|Win32
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Win32.Build.0 = Debug|Win32
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x64.ActiveCfg = Debug|x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x64.Build.0 = Debug|x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.DebugFast|Win32.ActiveCfg = Debug|Win32
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.DebugFast|Win32.Build.0 = Debug|Win32
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.DebugFast|x64.ActiveCfg = Debug|x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.DebugFast|x64.Build.0 = Debug|x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release_JITIL|Win32.ActiveCfg = Release|x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release_JITIL|x64.ActiveCfg = Release|x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release_JITIL|x64.Build.0 = Release|x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Win32.ActiveCfg = Release|Win32
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Win32.Build.0 = Release|Win32
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x64.ActiveCfg = Release|x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -67,7 +67,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wiiuse.lib rpcrt4.lib wxbase28ud.lib wxmsw28ud_core.lib"
AdditionalDependencies="xinput.lib comctl32.lib winmm.lib wiiuse.lib rpcrt4.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\Win32/Plugins\Plugin_WiimoteD.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\WiiUse\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
+51 -29
View File
@@ -24,6 +24,7 @@
#include "Config.h"
#include "EmuDefinitions.h" // for PadMapping
#include "EmuMain.h"
#include "main.h"
// Configuration file control names
@@ -242,10 +243,13 @@ Config::Config()
{
// Set all default values to zero
memset(this, 0, sizeof(Config));
Loaded = false;
}
void Config::Load(bool ChangePad)
{
Loaded = true;
std::string temp;
IniFile iniFile;
iniFile.Load(FULL_CONFIG_DIR "Wiimote.ini");
@@ -273,6 +277,7 @@ void Config::Load(bool ChangePad)
sprintf(SectionName, "Wiimote%i", i + 1);
iniFile.Get(SectionName, "NoTriggerFilter", &bNoTriggerFilter, false);
iniFile.Get(SectionName, "TriggerType", &Trigger.Type, Trigger.TRIGGER_OFF);
iniFile.Get(SectionName, "TriggerUpright", &Trigger.Upright, false);
iniFile.Get(SectionName, "TriggerRollRange", &Trigger.Range.Roll, 50);
iniFile.Get(SectionName, "TriggerPitchRange", &Trigger.Range.Pitch, false);
@@ -295,38 +300,49 @@ void Config::Load(bool ChangePad)
iniFile.Get(SectionName, gh3ControlNames[x], &WiiMoteEmu::PadMapping[i].GH3c.keyForControls[x], GH3DefaultControls[x]);
// Don't update this when we are loading settings from the ConfigBox
if(!ChangePad)
if (!ChangePad)
{
// This pad Id could possibly be higher than the number of pads that are connected,
// but we check later, when needed, that that is not the case
iniFile.Get(SectionName, "DeviceID", &WiiMoteEmu::PadMapping[i].ID, 0);
iniFile.Get(SectionName, "DeviceName", &WiiMoteEmu::PadMapping[i].Name, 0);
iniFile.Get(SectionName, "Enabled", &WiiMoteEmu::PadMapping[i].enabled, true);
}
// Joypad specific settings
// Current joypad device ID: PadMapping[i].ID
// Current joypad name: joyinfo[PadMapping[i].ID].Name
// Prevent a crash from illegal access to joyinfo that will only have values for
// the current amount of connected PadMapping
if((u32)WiiMoteEmu::PadMapping[i].ID >= WiiMoteEmu::joyinfo.size()) continue;
// Current joypad device ID: PadMapping[i].ID
// Current joypad name: PadMapping[i].Name
// Create a section name
std::string joySectionName = WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[i].ID].Name;
std::string JoySectionName = WiiMoteEmu::PadMapping[i].Name;
// Don't load settings for a non-connected device
if (!WiiMoteEmu::IsConnected(JoySectionName))
{
ERROR_LOG(PAD, "Slot %i: The device '%s' is not connected, will not load settings", i, JoySectionName.c_str());
continue;
}
// Don't load a blank ID
if (JoySectionName == "")
{
ERROR_LOG(PAD, "Slot %i has no device name, will not load settings", i);
continue;
}
iniFile.Get(joySectionName.c_str(), "left_x", &WiiMoteEmu::PadMapping[i].Axis.Lx, 0);
iniFile.Get(joySectionName.c_str(), "left_y", &WiiMoteEmu::PadMapping[i].Axis.Ly, 1);
iniFile.Get(joySectionName.c_str(), "right_x", &WiiMoteEmu::PadMapping[i].Axis.Rx, 2);
iniFile.Get(joySectionName.c_str(), "right_y", &WiiMoteEmu::PadMapping[i].Axis.Ry, 3);
iniFile.Get(joySectionName.c_str(), "l_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tl, 1004);
iniFile.Get(joySectionName.c_str(), "r_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tr, 1005);
iniFile.Get(joySectionName.c_str(), "DeadZoneL", &WiiMoteEmu::PadMapping[i].DeadZoneL, 0);
iniFile.Get(joySectionName.c_str(), "DeadZoneR", &WiiMoteEmu::PadMapping[i].DeadZoneR, 0);
iniFile.Get(joySectionName.c_str(), "TriggerType", &WiiMoteEmu::PadMapping[i].triggertype, 0);
iniFile.Get(joySectionName.c_str(), "Diagonal", &WiiMoteEmu::PadMapping[i].SDiagonal, "100%");
iniFile.Get(joySectionName.c_str(), "Circle2Square", &WiiMoteEmu::PadMapping[i].bCircle2Square, false);
iniFile.Get(joySectionName.c_str(), "RollInvert", &WiiMoteEmu::PadMapping[i].bRollInvert, false);
iniFile.Get(joySectionName.c_str(), "PitchInvert", &WiiMoteEmu::PadMapping[i].bPitchInvert, false);
iniFile.Get(JoySectionName.c_str(), "left_x", &WiiMoteEmu::PadMapping[i].Axis.Lx, 0);
iniFile.Get(JoySectionName.c_str(), "left_y", &WiiMoteEmu::PadMapping[i].Axis.Ly, 1);
iniFile.Get(JoySectionName.c_str(), "right_x", &WiiMoteEmu::PadMapping[i].Axis.Rx, 2);
iniFile.Get(JoySectionName.c_str(), "right_y", &WiiMoteEmu::PadMapping[i].Axis.Ry, 3);
iniFile.Get(JoySectionName.c_str(), "l_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tl, 1004);
iniFile.Get(JoySectionName.c_str(), "r_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tr, 1005);
iniFile.Get(JoySectionName.c_str(), "DeadZoneL", &WiiMoteEmu::PadMapping[i].DeadZoneL, 0);
iniFile.Get(JoySectionName.c_str(), "DeadZoneR", &WiiMoteEmu::PadMapping[i].DeadZoneR, 0);
iniFile.Get(JoySectionName.c_str(), "TriggerType", &WiiMoteEmu::PadMapping[i].triggertype, 0);
iniFile.Get(JoySectionName.c_str(), "Diagonal", &WiiMoteEmu::PadMapping[i].SDiagonal, "100%");
iniFile.Get(JoySectionName.c_str(), "Circle2Square", &WiiMoteEmu::PadMapping[i].bCircle2Square, false);
iniFile.Get(JoySectionName.c_str(), "RollInvert", &WiiMoteEmu::PadMapping[i].bRollInvert, false);
iniFile.Get(JoySectionName.c_str(), "PitchInvert", &WiiMoteEmu::PadMapping[i].bPitchInvert, false);
NOTICE_LOG(WIIMOTE, "Slot %i: Load settings for ID %i '%s'", i, WiiMoteEmu::PadMapping[i].ID, JoySectionName.c_str());
}
// Load the IR cursor settings if it's avaliable for the GameId, if not load the default settings
iniFile.Load(FULL_CONFIG_DIR "IR Pointer.ini");
@@ -375,6 +391,7 @@ void Config::Save(int Slot)
iniFile.Set(SectionName, "Enabled", WiiMoteEmu::PadMapping[i].enabled);
iniFile.Set(SectionName, "NoTriggerFilter", bNoTriggerFilter);
iniFile.Set(SectionName, "TriggerType", Trigger.Type);
iniFile.Set(SectionName, "TriggerUpright", Trigger.Upright);
iniFile.Set(SectionName, "TriggerRollRange", Trigger.Range.Roll);
iniFile.Set(SectionName, "TriggerPitchRange", Trigger.Range.Pitch);
@@ -400,18 +417,23 @@ void Config::Save(int Slot)
// Save the physical device ID number
iniFile.Set(SectionName, "DeviceID", WiiMoteEmu::PadMapping[i].ID);
iniFile.Set(SectionName, "DeviceName", WiiMoteEmu::PadMapping[i].Name);
// Joypad specific settings
// Current joypad device ID: PadMapping[i].ID
// Current joypad name: joyinfo[PadMapping[i].ID].Name
// Save joypad specific settings. Check for "PadMapping[i].ID < SDL_NumJoysticks()" to
// avoid reading a joyinfo that does't exist
if((u32)WiiMoteEmu::PadMapping[i].ID >= WiiMoteEmu::joyinfo.size()) continue;
// Current joypad device ID: PadMapping[i].ID
// Current joypad name: IDToName(PadMapping[i].ID])
// Create a new section name after the joypad name
std::string joySectionName = WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[i].ID].Name;
std::string joySectionName = WiiMoteEmu::IDToName(WiiMoteEmu::PadMapping[i].ID);
// Don't save a blank name
if (SectionName == "")
{
ERROR_LOG(WIIMOTE, "ID %i has no name, will not load", WiiMoteEmu::PadMapping[i].ID);
continue;
}
NOTICE_LOG(WIIMOTE, "Save settings for ID %i '%s' from PadMapping[%i]", WiiMoteEmu::PadMapping[i].ID, joySectionName.c_str(), i);
iniFile.Set(joySectionName.c_str(), "left_x", WiiMoteEmu::PadMapping[i].Axis.Lx);
iniFile.Set(joySectionName.c_str(), "left_y", WiiMoteEmu::PadMapping[i].Axis.Ly);
iniFile.Set(joySectionName.c_str(), "right_x", WiiMoteEmu::PadMapping[i].Axis.Rx);
@@ -41,6 +41,7 @@ struct Config
Config();
void Load(bool ChangePad = false);
void Save(int Slot = -1);
bool Loaded;
struct PadRange
{
@@ -59,6 +60,7 @@ struct Config
TRIGGER
};
int Type;
bool Upright;
PadRange Range;
};
struct PadNunchuck
@@ -34,6 +34,7 @@ BEGIN_EVENT_TABLE(WiimoteBasicConfigDialog,wxDialog)
EVT_CHECKBOX(ID_CONNECT_REAL, WiimoteBasicConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_USE_REAL, WiimoteBasicConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_SIDEWAYSDPAD, WiimoteBasicConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_UPRIGHTWIIMOTE, WiimoteBasicConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_MOTIONPLUSCONNECTED, WiimoteBasicConfigDialog::GeneralSettingsChanged)
EVT_CHOICE(ID_EXTCONNECTED, WiimoteBasicConfigDialog::GeneralSettingsChanged)
// IR cursor
@@ -207,9 +208,9 @@ void WiimoteBasicConfigDialog::CreateGUIControls()
// Emulated Wiimote
m_SidewaysDPad[i] = new wxCheckBox(m_Controller[i], ID_SIDEWAYSDPAD, wxT("Sideways D-Pad"));
m_SidewaysDPad[i]->SetValue(g_Config.bSidewaysDPad);
m_SizeEmu[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Emulated Wiimote"));
m_SizeEmu[i]->Add(m_SidewaysDPad[i], 0, wxEXPAND | wxALL, 5);
m_UprightWiimote[i] = new wxCheckBox(m_Controller[i], ID_UPRIGHTWIIMOTE, wxT("Upright Wiimote"));
m_UprightWiimote[i]->SetValue(g_Config.Trigger.Upright);
m_UprightWiimote[i]->SetToolTip(wxT("Treat the upright position as neutral for roll and pitch"));
//IR Pointer
m_TextScreenWidth[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Width: 000"));
@@ -251,6 +252,12 @@ void WiimoteBasicConfigDialog::CreateGUIControls()
m_CheckAR169[i]->Enable(false);
m_Crop[i]->Enable(false);
// Sizers
m_SizeEmu[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Emulated Wiimote"));
m_SizeEmu[i]->Add(m_SidewaysDPad[i], 0, wxEXPAND | wxALL, 5);
m_SizeEmu[i]->Add(m_UprightWiimote[i], 0, wxEXPAND | (wxLEFT | wxDOWN | wxRIGHT), 5);
m_SizerIRPointerScreen[i] = new wxBoxSizer(wxHORIZONTAL);
m_SizerIRPointerScreen[i]->Add(m_TextAR[i], 0, wxEXPAND | (wxTOP), 0);
m_SizerIRPointerScreen[i]->Add(m_CheckAR43[i], 0, wxEXPAND | (wxLEFT), 5);
@@ -391,6 +398,9 @@ void WiimoteBasicConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
case ID_SIDEWAYSDPAD:
g_Config.bSidewaysDPad = m_SidewaysDPad[Page]->IsChecked();
break;
case ID_UPRIGHTWIIMOTE:
g_Config.Trigger.Upright = m_UprightWiimote[Page]->IsChecked();
break;
case ID_MOTIONPLUSCONNECTED:
@@ -79,6 +79,7 @@ class WiimoteBasicConfigDialog : public wxDialog
// Emulated Wiimote settings
wxCheckBox *m_SidewaysDPad[4],
*m_UprightWiimote[4],
*m_WiimoteOnline[4],
*m_WiiMotionPlusConnected[4],
*m_CheckAR43[4],
@@ -126,6 +127,7 @@ class WiimoteBasicConfigDialog : public wxDialog
// Emulated Wiimote
ID_SIDEWAYSDPAD,
ID_UPRIGHTWIIMOTE,
ID_MOTIONPLUSCONNECTED,
ID_EXTCONNECTED,
IDC_WIMOTE_ON,
@@ -30,36 +30,15 @@
is only used the first time the pads are checked. */
void WiimotePadConfigDialog::DoChangeJoystick()
{
// Close the current pad, unless it's used by another slot
//if (PadMapping[notebookpage].enabled) PadClose(notebookpage);
WARN_LOG(WIIMOTE, "---- DoChangeJoystick ----");
// Before changing the pad we save potential changes to the current pad
DoSave(true);
// Load the settings for the new Id
g_Config.Load(true);
UpdateGUI(Page); // Update the GUI
// Open the new pad
if (WiiMoteEmu::PadMapping[Page].enabled) PadOpen(Page);
}
void WiimotePadConfigDialog::PadOpen(int Open) // Open for slot 1, 2, 3 or 4
{
// Check that we got a good pad
if (!WiiMoteEmu::joyinfo.at(WiiMoteEmu::PadMapping[Open].ID).Good)
{
DEBUG_LOG(WIIMOTE, "A bad pad was selected");
WiiMoteEmu::PadState[Open].joy = NULL;
return;
}
DEBUG_LOG(WIIMOTE, "Update the Slot %i handle to Id %i", Page, WiiMoteEmu::PadMapping[Open].ID);
WiiMoteEmu::PadState[Open].joy = SDL_JoystickOpen(WiiMoteEmu::PadMapping[Open].ID);
}
void WiimotePadConfigDialog::PadClose(int _Close) // Close for slot 1, 2, 3 or 4
{
if (SDL_JoystickOpened(WiiMoteEmu::PadMapping[_Close].ID)) SDL_JoystickClose(WiiMoteEmu::PadState[_Close].joy);
WiiMoteEmu::PadState[_Close].joy = NULL;
// Update the GUI
UpdateGUI(Page);
}
void WiimotePadConfigDialog::DoChangeDeadZone(bool Left)
@@ -90,30 +69,29 @@ void WiimotePadConfigDialog::DoChangeDeadZone(bool Left)
// Set the button text for all four Wiimotes
void WiimotePadConfigDialog::SetButtonTextAll(int id, char text[128])
{
for (int i = 0; i < 1; i++)
for (int i = 0; i < MAX_WIIMOTES; i++)
{
// Safety check to avoid crash
if ((int)WiiMoteEmu::joyinfo.size() > WiiMoteEmu::PadMapping[i].ID)
if (WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[i].ID].Name == WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[Page].ID].Name)
SetButtonText(id, text, i);
if (WiiMoteEmu::IDToName(WiiMoteEmu::PadMapping[i].ID) == WiiMoteEmu::IDToName(WiiMoteEmu::PadMapping[Page].ID))
{
SetButtonText(id, text, i);
DEBUG_LOG(PAD, "Updated button text for slot %i", i);
}
};
}
void WiimotePadConfigDialog::SaveButtonMappingAll(int Slot)
{
for (int i = 0; i < 4; i++)
{
// This can occur when no gamepad is detected
if ((int)WiiMoteEmu::joyinfo.size() > WiiMoteEmu::PadMapping[i].ID && WiiMoteEmu::PadMapping[i].ID >= 0)
if (WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[i].ID].Name == WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[Slot].ID].Name)
SaveButtonMapping(i, false, Slot);
for (int i = 0; i < MAX_WIIMOTES; i++)
{
if (WiiMoteEmu::IDToName(WiiMoteEmu::PadMapping[i].ID) == WiiMoteEmu::IDToName(WiiMoteEmu::PadMapping[Slot].ID))
SaveButtonMapping(i, false, Slot);
}
}
// Set dialog items from saved values
void WiimotePadConfigDialog::UpdateGUIButtonMapping(int controller)
{
NOTICE_LOG(WIIMOTE, "Load ButtonMapping | controller:%i", controller);
// Temporary storage
wxString tmp;
@@ -204,12 +182,19 @@ void WiimotePadConfigDialog::UpdateGUIButtonMapping(int controller)
void WiimotePadConfigDialog::SaveButtonMapping(int controller, bool DontChangeId, int FromSlot)
{
// Log
NOTICE_LOG(WIIMOTE, "SaveButtonMapping | controller:%i FromSlot:%i", controller, FromSlot);
// Temporary storage
wxString tmp;
long value;
// Save from or to the same or different slots
if (FromSlot == -1) FromSlot = controller;
// TEMPORARY
// There is only one slot at the moment
if (FromSlot > MAX_WIIMOTES-1) FromSlot = MAX_WIIMOTES-1;
// Replace "" with "-1" in the GUI controls
ToBlank(false);
@@ -218,7 +203,10 @@ void WiimotePadConfigDialog::SaveButtonMapping(int controller, bool DontChangeId
-1 that's a bug that should be fixed. Because the m_Joyname[] combo box should always show <No Gamepad Detected>, or a gamepad name, not a
a blank selection. */
if (!DontChangeId)
WiiMoteEmu::PadMapping[controller].ID = m_Joyname[FromSlot]->GetSelection();
{
WiiMoteEmu::PadMapping[controller].ID = WiiMoteEmu::joyinfo.at(m_Joyname[FromSlot]->GetSelection()).ID;
WiiMoteEmu::PadMapping[controller].Name = m_Joyname[FromSlot]->GetValue().mb_str();
}
// Set enabled or disable status
if (FromSlot == controller)
WiiMoteEmu::PadMapping[controller].enabled = true; //m_Joyattach[FromSlot]->GetValue(); // Only enable one
@@ -372,6 +360,11 @@ void WiimotePadConfigDialog::GetButtons(wxCommandEvent& event)
void WiimotePadConfigDialog::DoGetButtons(int _GetId)
{
DEBUG_LOG(WIIMOTE, "DoGetButtons");
bool _LiveUpdates = LiveUpdates;
LiveUpdates = false;
// Collect the starting values
// Get the current controller
@@ -399,7 +392,7 @@ void WiimotePadConfigDialog::DoGetButtons(int _GetId)
// Values used in this function
char format[128];
int Seconds = 4; // Seconds to wait for
int TimesPerSecond = 40; // How often to run the check
int TimesPerSecond = 60; // How often to run the check
// Values returned from InputCommon::GetButton()
int value; // Axis value
@@ -438,7 +431,7 @@ void WiimotePadConfigDialog::DoGetButtons(int _GetId)
m_ButtonMappingTimer->Start( floor((double)(1000 / TimesPerSecond)) );
#endif
DEBUG_LOG(WIIMOTE, "Timer Started for Pad:%i _GetId:%i"
"Allowed input is Axis:%i LeftRight:%i XInput:%i Button:%i Hat:%i\n",
" Allowed input is Axis:%i LeftRight:%i XInput:%i Button:%i Hat:%i\n",
WiiMoteEmu::PadMapping[Controller].ID, _GetId,
Axis, LeftRight, XInput, Button, Hat);
}
@@ -449,7 +442,7 @@ void WiimotePadConfigDialog::DoGetButtons(int _GetId)
else
{
InputCommon::GetButton(
WiiMoteEmu::joyinfo[PadID].joy, PadID, WiiMoteEmu::joyinfo[PadID].NumButtons, WiiMoteEmu::joyinfo[PadID].NumAxes, WiiMoteEmu::joyinfo[PadID].NumHats,
WiiMoteEmu::PadState[Page].joy, PadID,
g_Pressed, value, type, pressed, Succeed, Stop,
LeftRight, Axis, XInput, Button, Hat, NoTriggerFilter);
}
@@ -482,7 +475,7 @@ void WiimotePadConfigDialog::DoGetButtons(int _GetId)
}
// If we got a button
if(Succeed)
if (Succeed)
{
Stop = true;
// Write the number of the pressed button to the text box
@@ -491,10 +484,11 @@ void WiimotePadConfigDialog::DoGetButtons(int _GetId)
}
// Stop the timer
if(Stop)
if (Stop)
{
m_ButtonMappingTimer->Stop();
GetButtonWaitingTimer = 0;
LiveUpdates = _LiveUpdates;
/* Update the button mapping for all slots that use this device. (It
doesn't make sense to have several slots controlled by the same
@@ -545,12 +539,12 @@ void WiimotePadConfigDialog::Convert2Box(int &x)
// Update the input status boxes
void WiimotePadConfigDialog::PadGetStatus()
{
//DEBUG_LOG(WIIMOTE, "SDL_WasInit: %i", SDL_WasInit(0));
//DEBUG_LOG(WIIMOTE, "PadGetStatus");
/* Return if it's not detected. The ID should never be less than zero here,
it can only be that because of a manual ini file change, but we make
that check anway. */
if(WiiMoteEmu::PadMapping[Page].ID < 0 || WiiMoteEmu::PadMapping[Page].ID >= SDL_NumJoysticks())
if (WiiMoteEmu::PadMapping[Page].ID < 0 || WiiMoteEmu::PadMapping[Page].ID >= SDL_NumJoysticks())
{
m_TStatusLeftIn[Page]->SetLabel(wxT("Not connected"));
m_TStatusLeftOut[Page]->SetLabel(wxT("Not connected"));
@@ -574,15 +568,13 @@ void WiimotePadConfigDialog::PadGetStatus()
}
// Get physical device status
int PhysicalDevice = WiiMoteEmu::PadMapping[Page].ID;
int ID = WiiMoteEmu::PadMapping[Page].ID;
int TriggerType = WiiMoteEmu::PadMapping[Page].triggertype;
// Check that Dolphin is in focus, otherwise don't update the pad status
//if (IsFocus())
WiiMoteEmu::GetJoyState(WiiMoteEmu::PadState[Page], WiiMoteEmu::PadMapping[Page], Page, WiiMoteEmu::joyinfo.at(WiiMoteEmu::PadMapping[Page].ID).NumButtons);
WiiMoteEmu::GetJoyState(WiiMoteEmu::PadState[Page], WiiMoteEmu::PadMapping[Page], Page);
// Analog stick
// Set Deadzones perhaps out of function
//int deadzone = (int)(((float)(128.00/100.00)) * (float)(PadMapping[_numPAD].deadzone+1));
@@ -695,16 +687,40 @@ void WiimotePadConfigDialog::PadGetStatus()
wxT("%03i"), TriggerRight));
}
// Slow timer, once a second
void WiimotePadConfigDialog::Update(wxTimerEvent& WXUNUSED(event))
{
if (!LiveUpdates) return;
// Search for connected devices and update dialog
int OldNumDIDevices = WiiMoteEmu::NumDIDevices;
WiiMoteEmu::NumDIDevices = InputCommon::SearchDIDevices();
// Update if a pad has been connected/disconnected. Todo: Add a better check that also takes into consideration the pad id
// and other things to ensure nothing has changed
//DEBUG_LOG(WIIMOTE, "Found %i devices", WiiMoteEmu::NumDIDevices);
//DEBUG_LOG(WIIMOTE, "Update: %i %i", OldNumPads, WiiMoteEmu::NumPads);
if (OldNumDIDevices != WiiMoteEmu::NumDIDevices)
{
WiiMoteEmu::LocalSearchDevicesReset(WiiMoteEmu::joyinfo, WiiMoteEmu::NumPads);
WiimotePadConfigDialog::UpdateDeviceList();
}
}
// Populate the advanced tab
void WiimotePadConfigDialog::UpdatePad(wxTimerEvent& WXUNUSED(event))
{
if (!WiiMoteEmu::IsPolling()) return;
//DEBUG_LOG(WIIMOTE, "UpdatePad");
// Show the current status
/*
#ifdef SHOW_PAD_STATUS
m_pStatusBar->SetLabel(wxString::Format(
"%s", ShowStatus(notebookpage).c_str()
));
#endif*/
m_pStatusBar->SetLabel(wxString::FromAscii(InputCommon::DoShowStatus(
Page, m_Joyname[Page]->GetSelection(),
WiiMoteEmu::PadMapping, WiiMoteEmu::PadState, WiiMoteEmu::joyinfo
).c_str()));
#endif
//LogMsg("Abc%s\n", ShowStatus(notebookpage).c_str());
@@ -98,6 +98,7 @@ BEGIN_EVENT_TABLE(WiimotePadConfigDialog,wxDialog)
EVT_BUTTON(IDB_TRIGGER_L, WiimotePadConfigDialog::GetButtons)
EVT_BUTTON(IDB_TRIGGER_R, WiimotePadConfigDialog::GetButtons)
EVT_TIMER(IDTM_BUTTON, WiimotePadConfigDialog::OnButtonTimer)
EVT_TIMER(IDTM_UPDATE, WiimotePadConfigDialog::Update)
EVT_TIMER(IDTM_UPDATE_PAD, WiimotePadConfigDialog::UpdatePad)
END_EVENT_TABLE()
@@ -107,14 +108,25 @@ WiimotePadConfigDialog::WiimotePadConfigDialog(wxWindow *parent, wxWindowID id,
{
#if wxUSE_TIMER
m_ButtonMappingTimer = new wxTimer(this, IDTM_BUTTON);
m_UpdatePad = new wxTimer(this, IDTM_UPDATE_PAD);
m_Update = new wxTimer(this, IDTM_UPDATE);
m_UpdatePad = new wxTimer(this, IDTM_UPDATE_PAD);
// Reset values
GetButtonWaitingID = 0;
GetButtonWaitingTimer = 0;
// Settings
// Only tested in Windows
#ifdef _WIN32
LiveUpdates = true;
#else
LiveUpdates = false;
#endif
// Start the permanent timer
const int TimesPerSecond = 30;
// Start the slow timer
int TimesPerSecond = 2;
m_Update->Start( floor((double)(1000 / TimesPerSecond)) );
// Start the fast timer
TimesPerSecond = 30;
m_UpdatePad->Start( floor((double)(1000 / TimesPerSecond)) );
#endif
@@ -128,6 +140,9 @@ WiimotePadConfigDialog::WiimotePadConfigDialog(wxWindow *parent, wxWindowID id,
// Set control values
UpdateGUI();
// Update device list
UpdateDeviceList();
wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
wxKeyEventHandler(WiimotePadConfigDialog::OnKeyDown),
@@ -204,9 +219,13 @@ void WiimotePadConfigDialog::OnClose(wxCloseEvent& event)
{
g_FrameOpen = false;
SaveButtonMappingAll(Page);
if(m_UpdatePad)
m_UpdatePad->Stop();
// Stop timers
if(m_Update) m_Update->Stop();
if(m_UpdatePad) m_UpdatePad->Stop();
if(m_ButtonMappingTimer) m_ButtonMappingTimer->Stop();
INFO_LOG(WIIMOTE, "All timers stopped");
g_Config.Save();
event.Skip();
}
@@ -228,18 +247,20 @@ void WiimotePadConfigDialog::CloseClick(wxCommandEvent& event)
void WiimotePadConfigDialog::DoSave(bool ChangePad, int Slot)
{
WARN_LOG(WIIMOTE, "DoSave - %i slot %i", ChangePad, Slot);
// Replace "" with "-1" before we are saving
ToBlank(false);
if(ChangePad)
{
// Since we are selecting the pad to save to by the Id we can't update it when we change the pad
for(int i = 0; i < 4; i++)
for(int i = 0; i < MAX_WIIMOTES; i++)
SaveButtonMapping(i, true);
// Save the settings for the current pad
g_Config.Save(Slot);
// Now we can update the ID
WiiMoteEmu::PadMapping[Page].ID = m_Joyname[Page]->GetSelection();
UpdateID();
}
else
{
@@ -251,8 +272,14 @@ void WiimotePadConfigDialog::DoSave(bool ChangePad, int Slot)
// Then change it back to ""
ToBlank();
DEBUG_LOG(WIIMOTE, "WiiMoteEmu::PadMapping[%i].ID = %i", Page, m_Joyname[Page]->GetSelection());
}
void WiimotePadConfigDialog::UpdateID()
{
INFO_LOG(WIIMOTE, "PadMapping[%i].ID = %i from %i",
Page, WiiMoteEmu::joyinfo.at(m_Joyname[Page]->GetSelection()).ID, WiiMoteEmu::PadMapping[Page].ID);
WiiMoteEmu::PadMapping[Page].ID = WiiMoteEmu::joyinfo.at(m_Joyname[Page]->GetSelection()).ID;
WiiMoteEmu::PadMapping[Page].Name = m_Joyname[Page]->GetValue().mb_str();
WiiMoteEmu::PadState[Page].joy = WiiMoteEmu::joyinfo.at(m_Joyname[Page]->GetSelection()).joy;
}
// Bitmap box and dot
@@ -325,24 +352,40 @@ wxBitmap WiimotePadConfigDialog::CreateBitmapClear()
return bitmap;
}
void WiimotePadConfigDialog::UpdateDeviceList()
{
if (!ControlsCreated) return;
DEBUG_LOG(WIIMOTE, "UpdateDeviceList");
for (int i = 0; i < MAX_WIIMOTES; i++)
{
// Save current selection
//std::string CurrentSel = m_Joyname[i]->GetValue().mb_str();
m_Joyname[i]->Clear();
// Search for devices and add them to the device list
if (WiiMoteEmu::NumPads > 0)
{
for (int j = 0; j < WiiMoteEmu::NumPads; j++)
m_Joyname[i]->Append(wxString::FromAscii(WiiMoteEmu::joyinfo.at(j).Name.c_str()));
// Set selection
for (int j = 0; j < WiiMoteEmu::NumPads; j++)
if (WiiMoteEmu::joyinfo.at(j).Name == WiiMoteEmu::PadMapping[i].Name) m_Joyname[i]->SetSelection(j);
if (m_Joyname[i]->GetSelection() == -1) m_Joyname[i]->SetSelection(0);
// Load settings
DoChangeJoystick();
}
else
{
m_Joyname[i]->Append(wxString::FromAscii("<No Gamepad Detected>"));
m_Joyname[i]->SetSelection(0);
}
}
}
void WiimotePadConfigDialog::CreatePadGUIControls()
{
// Search for devices and add them to the device list
wxArrayString StrJoyname; // The string array
if (WiiMoteEmu::NumGoodPads > 0)
{
for (int x = 0; x < (int)WiiMoteEmu::joyinfo.size(); x++)
StrJoyname.Add(wxString::FromAscii(WiiMoteEmu::joyinfo[x].Name.c_str()));
}
else
{
StrJoyname.Add(wxString::FromAscii("<No Gamepad Detected>"));
}
// The tilt list
wxArrayString StrTilt;
StrTilt.Add(wxString::FromAscii("<Off>"));
@@ -372,13 +415,17 @@ void WiimotePadConfigDialog::CreatePadGUIControls()
wxArrayString StrCcTriggers;
StrCcTriggers.Add(wxString::FromAscii("Keyboard"));
StrCcTriggers.Add(wxString::FromAscii("Triggers"));
#ifdef SHOW_PAD_STATUS
m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxSize(-1, 600));
m_pStatusBar = new wxStaticText(this, IDT_DEBUGGING, wxT("Debugging"), wxPoint(250, 250), wxDefaultSize);
#else
m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
#endif
for (int i = 0; i < MAX_WIIMOTES; i++)
{
m_Controller[i] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1 + i, wxDefaultPosition, wxDefaultSize);
{
m_Controller[i] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1 + i, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[i], wxString::Format(wxT("Wiimote %d"), i+1));
// A small type font
@@ -387,9 +434,8 @@ void WiimotePadConfigDialog::CreatePadGUIControls()
// Configuration controls sizes
static const int TxtW = 50, TxtH = 19, BtW = 75, BtH = 20;
// Controller
m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, StrJoyname[0], wxDefaultPosition, wxSize(200, -1), StrJoyname, wxCB_READONLY);
m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxDefaultPosition, wxSize(200, -1), 0, NULL, wxCB_READONLY);
// Circle to square
m_CheckC2S[i] = new wxCheckBox(m_Controller[i], IDC_LEFT_C2S, wxT("Circle To Square"));
@@ -946,7 +992,6 @@ void WiimotePadConfigDialog::CreatePadGUIControls()
}
m_Apply = new wxButton(this, ID_APPLY, wxT("Apply"));
m_Close = new wxButton(this, ID_CLOSE, wxT("Close"));
m_Close->SetToolTip(wxT("Apply and Close"));
@@ -1037,14 +1082,16 @@ void WiimotePadConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
void WiimotePadConfigDialog::UpdateGUI(int Slot)
{
DEBUG_LOG(WIIMOTE, "UpdateGUI");
UpdateGUIButtonMapping(Page);
DoChangeDeadZone(true); DoChangeDeadZone(false);
// Linux has no FindItem()
// Disable all pad items if no pads are detected
if(ControlsCreated)
if (ControlsCreated)
{
bool PadEnabled = WiiMoteEmu::NumGoodPads != 0;
bool PadEnabled = WiiMoteEmu::NumPads != 0;
#ifdef _WIN32
for(int i = IDB_ANALOG_LEFT_X; i <= IDB_TRIGGER_R; i++) m_Notebook->FindItem(i)->Enable(PadEnabled);
m_Notebook->FindItem(IDC_JOYNAME)->Enable(PadEnabled);
@@ -59,9 +59,11 @@ class WiimotePadConfigDialog : public wxDialog
void Convert2Box(int &x);
void ConvertToString();
void OnButtonTimer(wxTimerEvent& WXUNUSED(event)) { DoGetButtons(GetButtonWaitingID); }
void Update(wxTimerEvent& WXUNUSED(event));
void UpdatePad(wxTimerEvent& WXUNUSED(event));
wxTimer *m_UpdatePad,
wxTimer *m_Update,
*m_UpdatePad,
*m_ButtonMappingTimer;
wxStaticBitmap *m_bmpDotLeftIn[4],
@@ -74,6 +76,7 @@ class WiimotePadConfigDialog : public wxDialog
DECLARE_EVENT_TABLE();
bool ControlsCreated;
bool LiveUpdates;
int Page, BoxW, BoxH, g_Pressed;
wxNotebook *m_Notebook;
@@ -142,7 +145,9 @@ class WiimotePadConfigDialog : public wxDialog
*m_Button_GH3[GH3_CONTROLS][4],
*m_bGH3_Analog[4];
wxStaticText *m_TextScreenWidth[4], *m_TextScreenHeight[4], *m_TextScreenLeft[4], *m_TextScreenTop[4], *m_TextAR[4],
wxStaticText
*m_pStatusBar,
*m_TextScreenWidth[4], *m_TextScreenHeight[4], *m_TextScreenLeft[4], *m_TextScreenTop[4], *m_TextAR[4],
*m_tAnalogX[8], *m_tAnalogY[8], *m_TiltTextRoll[4], *m_TiltTextPitch[4],
*m_CheckC2SLabel[4], *m_ComboDeadZoneLabel[4], *m_TStatusLeftIn[4], *m_TStatusLeftOut[4], *m_TStatusRightIn[4], *m_TStatusRightOut[4],
*m_TriggerStatusL[4], *m_TriggerStatusR[4], *m_TriggerStatusLx[4], *m_TriggerStatusRx[4],
@@ -178,10 +183,12 @@ class WiimotePadConfigDialog : public wxDialog
{
ID_CLOSE = 1000,
ID_APPLY,
IDTM_EXIT,
IDTM_EXIT, // Timer
IDTM_BUTTON,
IDTM_UPDATE_PAD, // Timer
IDTM_UPDATE,
IDTM_UPDATE_PAD,
IDT_DEBUGGING,
ID_NOTEBOOK,
ID_CONTROLLERPAGE1,
ID_CONTROLLERPAGE2,
@@ -246,6 +253,7 @@ class WiimotePadConfigDialog : public wxDialog
};
void OnClose(wxCloseEvent& event);
void UpdateDeviceList();
void CreatePadGUIControls();
void GeneralSettingsChanged(wxCommandEvent& event);
@@ -257,8 +265,9 @@ class WiimotePadConfigDialog : public wxDialog
void SaveKeyboardMapping(int Controller, int Id, int Key);
void ToBlank(bool ToBlank = true);
void PadGetStatus();
void UpdateID();
void DoSave(bool ChangePad = false, int Slot = -1);
void DoChangeJoystick(); void PadOpen(int Open); void PadClose(int Close); void DoChangeDeadZone(bool Left);
void DoChangeJoystick(); void DoChangeDeadZone(bool Left);
void OnButtonClick(wxCommandEvent& event);
// Configure buttons
@@ -57,7 +57,8 @@ wiimote_key g_ExtKey; // The extension encryption key
bool g_Encryption; // Encryption on or off
// Gamepad input
int NumPads = 0, NumGoodPads = 0; // Number of goods pads
int NumPads = 0, NumDIDevices = 0; // Number of pads
bool SDLPolling = true;
std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
InputCommon::CONTROLLER_STATE_NEW PadState[4];
InputCommon::CONTROLLER_MAPPING_NEW PadMapping[4];
@@ -182,7 +182,8 @@ static const u8 partially_id[] =
};
// Gamepad input
extern int NumPads, NumGoodPads; // Number of goods pads
extern int NumPads, NumDIDevices; // Number of pads
extern bool SDLPolling; // Turn off polling
extern std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
extern InputCommon::CONTROLLER_STATE_NEW PadState[4];
extern InputCommon::CONTROLLER_MAPPING_NEW PadMapping[4];
@@ -22,6 +22,7 @@
#include "../../../Core/InputCommon/Src/XInput.h"
#include "Common.h" // Common
#include "LogManager.h"
#include "MathUtil.h"
#include "StringUtil.h" // for ArrayToString()
#include "IniFile.h"
@@ -59,7 +60,8 @@ void TiltTest(u8 x, u8 y, u8 z)
std::string To = StringFromFormat("%s\nTo: X:%i Y:%i Z:%i Roll:%s Pitch:%s", From.c_str(), x, y, z,
(_Roll >= 0) ? StringFromFormat(" %03i", (int)_Roll).c_str() : StringFromFormat("%04i", (int)_Roll).c_str(),
(_Pitch >= 0) ? StringFromFormat(" %03i", (int)_Pitch).c_str() : StringFromFormat("%04i", (int)_Pitch).c_str());
DEBUG_LOG(WIIMOTE, "%s", To.c_str());
ConsoleListener* Console = LogManager::GetInstance()->getConsoleListener();
Console->CustomLog(StringFromFormat("\n%s", To.c_str()).c_str());
}
@@ -100,14 +102,29 @@ void PitchDegreeToAccelerometer(float _Roll, float _Pitch, u8 &_x, u8 &_y, u8 &_
// In these cases we can use the simple and accurate formula
if(g_Config.Trigger.Range.Pitch == 0)
{
x = sin(_Roll);
z = cos(_Roll);
if (!g_Config.Trigger.Upright)
{
x = sin(_Roll);
z = cos(_Roll);
}
else
{
z = sin(_Roll);
y = -cos(_Roll);
}
}
else if (g_Config.Trigger.Range.Roll == 0)
{
y = sin(_Pitch);
z = cos(_Pitch);
if (!g_Config.Trigger.Upright)
{
y = sin(_Pitch);
z = cos(_Pitch);
}
else
{
x = -sin(_Pitch);
y = -cos(_Pitch);
}
}
else
{
@@ -118,16 +135,28 @@ void PitchDegreeToAccelerometer(float _Roll, float _Pitch, u8 &_x, u8 &_y, u8 &_
and Pitch. But if we select a Z from the smallest of the absolute
value of cos(Roll) and cos (Pitch) we get the right values. */
// ---------
if (abs(cos(_Roll)) < abs(cos(_Pitch))) z = cos(_Roll); else z = cos(_Pitch);
/* I got these from reversing the calculation in
PitchAccelerometerToDegree() in a math program I don't know if we
can derive these from some kind of matrix or something */
float x_num = 2 * tanf(0.5f * _Roll) * z;
float x_den = pow2f(tanf(0.5f * _Roll)) - 1;
x = - (x_num / x_den);
float y_num = 2 * tanf(0.5f * _Pitch) * z;
float y_den = pow2f(tanf(0.5f * _Pitch)) - 1;
y = - (y_num / y_den);
if (!g_Config.Trigger.Upright)
{
if (abs(cos(_Roll)) < abs(cos(_Pitch))) z = cos(_Roll); else z = cos(_Pitch);
/* I got these from reversing the calculation in
PitchAccelerometerToDegree() in a math program. */
float x_num = 2 * tanf(0.5f * _Roll) * z;
float x_den = pow2f(tanf(0.5f * _Roll)) - 1;
x = - (x_num / x_den);
float y_num = 2 * tanf(0.5f * _Pitch) * z;
float y_den = pow2f(tanf(0.5f * _Pitch)) - 1;
y = - (y_num / y_den);
}
else
{
if (abs(-cos(_Roll)) < abs(-cos(_Pitch))) y = -cos(_Roll); else y = -cos(_Pitch);
float z_num = 2 * tanf(0.5f * _Roll) * y;
float z_den = pow2f(tanf(0.5f * _Roll)) - 1;
z = (z_num / z_den);
float x_num = 2 * tanf(0.5f * _Pitch) * y;
float x_den = pow2f(tanf(0.5f * _Pitch)) - 1;
x = - (x_num / x_den);
}
}
// Multiply with the neutral of z and its g
@@ -145,9 +174,18 @@ void PitchDegreeToAccelerometer(float _Roll, float _Pitch, u8 &_x, u8 &_y, u8 &_
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(g_Config.Trigger.Range.Roll != 0) _x = ix;
if(g_Config.Trigger.Range.Pitch != 0) _y = iy;
_z = iz;
if (!g_Config.Trigger.Upright)
{
if(g_Config.Trigger.Range.Roll != 0) _x = ix;
if(g_Config.Trigger.Range.Pitch != 0) _y = iy;
_z = iz;
}
else
{
if(g_Config.Trigger.Range.Roll != 0) _z = iz;
if(g_Config.Trigger.Range.Pitch != 0) _x = ix;
_y = iy;
}
}
// Accelerometer to roll and pitch angles
@@ -167,17 +205,34 @@ void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch, in
float y = AccelerometerToG((float)_y, (float)g_wm.cal_zero.y, (float)g_wm.cal_g.y);
float z = AccelerometerToG((float)_z, (float)g_wm.cal_zero.z, (float)g_wm.cal_g.z);
// 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)
if (!g_Config.Trigger.Upright)
{
// Calculate the degree
Roll = InputCommon::Rad2Deg(atan2(x, z));
}
// 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 degree
Roll = InputCommon::Rad2Deg(atan2(x, z));
}
//if (abs(_y - g_wm.cal_zero.y) <= g_wm.cal_g.y)
//if (abs(_y - g_wm.cal_zero.y) <= g_wm.cal_g.y)
{
// Calculate the degree
Pitch = InputCommon::Rad2Deg(atan2(y, z));
}
}
else
{
// Calculate the degree
Pitch = InputCommon::Rad2Deg(atan2(y, z));
//if (abs(accel->z - ac->cal_zero.z) <= ac->cal_g.x)
{
// Calculate the degree
Roll = InputCommon::Rad2Deg(atan2(z, -y));
}
//if (abs(_x - g_wm.cal_zero.x) <= g_wm.cal_g.x)
{
// Calculate the degree
Pitch = InputCommon::Rad2Deg(atan2(-x, -y));
}
}
_Roll = (int)Roll;
@@ -187,9 +242,16 @@ void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch, in
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;
Roll = InputCommon::Rad2Deg(atan2(x, z));
Pitch = InputCommon::Rad2Deg(atan2(y, z));
if (!g_Config.Trigger.Upright)
{
Roll = InputCommon::Rad2Deg(atan2(x, z));
Pitch = InputCommon::Rad2Deg(atan2(y, z));
}
else
{
Roll = InputCommon::Rad2Deg(atan2(z, -y));
Pitch = InputCommon::Rad2Deg(atan2(-x, -y));
}
_RollAdj = (int)Roll;
_PitchAdj = (int)Pitch;
}
+26 -26
View File
@@ -34,7 +34,12 @@
#include "Encryption.h" // for extension encryption
#include "Config.h" // for g_Config
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigPadDlg.h"
#endif
extern SWiimoteInitialize g_WiimoteInitialize;
extern WiimotePadConfigDialog *m_PadConfigFrame;
namespace WiiMoteEmu
{
@@ -438,9 +443,9 @@ void Initialize()
/* Populate joyinfo for all attached devices and do g_Config.Load() if the
configuration window is not already open, if it's already open we
continue with the settings we have */
if(!g_FrameOpen)
if (!m_PadConfigFrame)
{
Search_Devices(joyinfo, NumPads, NumGoodPads);
LocalSearchDevices(joyinfo, NumPads);
}
// Copy extension id and calibration to its register, g_Config.Load() is needed before this
@@ -486,7 +491,6 @@ void DoState(PointerWrap &p)
p.Do(g_Encryption);
p.Do(NumPads);
p.Do(NumGoodPads);
p.Do(joyinfo);
p.DoArray(PadState, 4);
p.DoArray(PadMapping, 4);
@@ -509,20 +513,16 @@ void Shutdown(void)
for (int i = 0; i < 1; i++)
{
if (PadMapping[i].enabled && joyinfo.size() > (u32)PadMapping[i].ID)
if (joyinfo.at(PadMapping[i].ID).Good)
{
INFO_LOG(WIIMOTE, "ShutDown: %i", PadState[i].joy);
/* SDL_JoystickClose() crashes for some reason so I avoid this
for now, SDL_Quit() should close the pads to I think */
//if(SDL_JoystickOpened(PadMapping[i].ID)) SDL_JoystickClose(PadState[i].joy);
//PadState[i].joy = NULL;
}
INFO_LOG(WIIMOTE, "ShutDown: %i", PadState[i].joy);
/* SDL_JoystickClose() crashes for some reason so I avoid this
for now, SDL_Quit() should close the pads to I think */
//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();
@@ -693,21 +693,8 @@ void ControlChannel(u16 _channelID, const void* _pData, u32 _Size)
of times per second. */
void Update()
{
readKeyboard();
//LOG(WIIMOTE, "Wiimote_Update");
//INFO_LOG(WIIMOTE, "Emu Update: %i", g_ReportingMode);
// Check if the pad state should be updated
if ((g_Config.Trigger.Type == g_Config.Trigger.TRIGGER || g_Config.Trigger.Type == g_Config.Trigger.ANALOG1 || g_Config.Trigger.Type == g_Config.Trigger.ANALOG2
|| g_Config.Nunchuck.Type == g_Config.Nunchuck.ANALOG1 || g_Config.Nunchuck.Type == g_Config.Nunchuck.ANALOG2
|| g_Config.ClassicController.LType == g_Config.ClassicController.ANALOG1 || g_Config.ClassicController.LType == g_Config.ClassicController.ANALOG2
|| g_Config.ClassicController.RType == g_Config.ClassicController.ANALOG1 || g_Config.ClassicController.RType == g_Config.ClassicController.ANALOG2)
&& NumGoodPads > 0 && joyinfo.size() > (u32)PadMapping[0].ID)
{
const int Page = 0;
WiiMoteEmu::GetJoyState(PadState[Page], PadMapping[Page], Page, joyinfo[PadMapping[Page].ID].NumButtons);
}
switch(g_ReportingMode)
{
case 0:
@@ -721,9 +708,22 @@ void Update()
// Potentially send a delayed acknowledgement to an InterruptChannel() Output
CheckAckDelay();
ReadKeyboard();
// Check if the pad state should be updated
if ((g_Config.Trigger.Type == g_Config.Trigger.TRIGGER || g_Config.Trigger.Type == g_Config.Trigger.ANALOG1 || g_Config.Trigger.Type == g_Config.Trigger.ANALOG2
|| g_Config.Nunchuck.Type == g_Config.Nunchuck.ANALOG1 || g_Config.Nunchuck.Type == g_Config.Nunchuck.ANALOG2
|| g_Config.ClassicController.LType == g_Config.ClassicController.ANALOG1 || g_Config.ClassicController.LType == g_Config.ClassicController.ANALOG2
|| g_Config.ClassicController.RType == g_Config.ClassicController.ANALOG1 || g_Config.ClassicController.RType == g_Config.ClassicController.ANALOG2)
&& NumPads > 0 && joyinfo.size() > (u32)PadMapping[0].ID)
{
const int Page = 0;
WiiMoteEmu::GetJoyState(PadState[Page], PadMapping[Page], Page);
}
}
void readKeyboard()
void ReadKeyboard()
{
#if defined(HAVE_X11) && HAVE_X11
XEvent E;
+9 -3
View File
@@ -41,7 +41,7 @@ void Shutdown(void);
void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size);
void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) ;
void Update();
void readKeyboard();
void ReadKeyboard();
// Recordings
void LoadRecordedMovements();
@@ -52,8 +52,14 @@ void UpdateEeprom();
void UpdateExtRegisterBlocks();
// Gamepad
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads);
void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONTROLLER_MAPPING_NEW _PadMapping, int controller, int NumButtons);
bool LocalSearchDevices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads);
bool LocalSearchDevicesReset(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads);
bool DoLocalSearchDevices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads);
bool IsConnected(std::string Name);
bool IsPolling();
void EnablePolling(bool Enable);
std::string IDToName(int ID);
void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONTROLLER_MAPPING_NEW _PadMapping, int controller);
void PadStateAdjustments(int &Lx, int &Ly, int &Rx, int &Ry, int &Tl, int &Tr);
// Accelerometer
+136 -25
View File
@@ -23,6 +23,7 @@
#include "../../../Core/InputCommon/Src/XInput.h"
#include "Common.h" // Common
#include "LogManager.h"
#include "StringUtil.h" // for ArrayToString()
#include "IniFile.h"
#include "pluginspecs_wiimote.h"
@@ -35,37 +36,138 @@
#include "Encryption.h" // for extension encryption
#include "Config.h" // for g_Config
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigPadDlg.h"
#endif
extern SWiimoteInitialize g_WiimoteInitialize;
extern WiimotePadConfigDialog *m_PadConfigFrame;
namespace WiiMoteEmu
{
// Fill joyinfo with the current connected devices
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
bool LocalSearchDevices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads)
{
bool WasGotten = InputCommon::SearchDevices(_joyinfo, _NumPads, _NumGoodPads);
//DEBUG_LOG(PAD, "LocalSearchDevices");
bool Success = InputCommon::SearchDevices(_joyinfo, _NumPads);
DoLocalSearchDevices(_joyinfo, _NumPads);
return Success;
}
bool LocalSearchDevicesReset(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads)
{
DEBUG_LOG(CONSOLE, "LocalSearchDevicesReset");
// Turn off device polling while resetting
EnablePolling(false);
bool Success = InputCommon::SearchDevicesReset(_joyinfo, _NumPads);
EnablePolling(true);
DoLocalSearchDevices(_joyinfo, _NumPads);
return Success;
}
// Fill joyinfo with the current connected devices
bool DoLocalSearchDevices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads)
{
//DEBUG_LOG(WIIMOTE, "LocalSearchDevices");
// Turn off device polling while searching
WiiMoteEmu::EnablePolling(false);
bool bReturn = InputCommon::SearchDevices(_joyinfo, _NumPads);
// Warn the user if no gamepads are detected
if (_NumGoodPads == 0 && g_EmulatorRunning)
if (_NumPads == 0 && g_EmulatorRunning)
{
//PanicAlert("nJoy: No Gamepad Detected");
//PanicAlert("Wiimote: No Gamepad Detected");
//return false;
}
// Load PadMapping[] etc
g_Config.Load();
// Load the first time
if (!g_Config.Loaded) g_Config.Load();
// Update the PadState[].joy handle
for (int i = 0; i < 1; i++)
{
if (PadMapping[i].enabled && joyinfo.size() > (u32)PadMapping[i].ID)
if(joyinfo.at(PadMapping[i].ID).Good)
PadState[i].joy = SDL_JoystickOpen(PadMapping[i].ID);
// If the saved ID matches, select this device for this slot
bool Match = false;
for (int i = 0; i < MAX_WIIMOTES; i++)
{
for (int j = 0; j < joyinfo.size(); j++)
{
if (joyinfo.at(j).Name == PadMapping[i].Name)
{
PadState[i].joy = joyinfo.at(j).joy;
Match = true;
//INFO_LOG(WIIMOTE, "Slot %i: '%s' %06i", i, joyinfo.at(j).Name.c_str(), PadState[i].joy);
}
}
if (!Match) PadState[i].joy = NULL;
}
return WasGotten;
WiiMoteEmu::EnablePolling(true);
return bReturn;
}
// Is the device connected?
// ----------------
bool IsConnected(std::string Name)
{
for (int i = 0; i < joyinfo.size(); i++)
{
DEBUG_LOG(WIIMOTE, "Pad %i: IsConnected checking '%s' against '%s'", i, joyinfo.at(i).Name.c_str(), Name.c_str());
if (joyinfo.at(i).Name == Name)
return true;
}
}
// See description of the equivalent functions in nJoy.cpp...
// ----------------
bool IsPolling()
{
return true;
/*
if (!SDLPolling || SDL_JoystickEventState(SDL_QUERY) == SDL_ENABLE)
return false;
else
return true;
*/
}
void EnablePolling(bool Enable)
{
/*
if (Enable)
{
SDLPolling = true;
SDL_JoystickEventState(SDL_IGNORE);
}
else
{
SDLPolling = false;
SDL_JoystickEventState(SDL_ENABLE);
}
*/
}
// ID to Name
// ----------------
std::string IDToName(int ID)
{
for (int i = 0; i < joyinfo.size(); i++)
{
//DEBUG_LOG(WIIMOTE, "IDToName: ID %i id %i %s", ID, i, joyinfo.at(i).Name.c_str());
if (joyinfo.at(i).ID == ID)
return joyinfo.at(i).Name;
}
return "";
}
// Return adjusted input values
void PadStateAdjustments(int &Lx, int &Ly, int &Rx, int &Ry, int &Tl, int &Tr)
{
@@ -119,11 +221,20 @@ void PadStateAdjustments(int &Lx, int &Ly, int &Rx, int &Ry, int &Tl, int &Tr)
Function: Updates the PadState struct with the current pad status. The input
value "controller" is for a virtual controller 0 to 3. */
void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONTROLLER_MAPPING_NEW _PadMapping, int controller, int NumButtons)
void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONTROLLER_MAPPING_NEW _PadMapping, int controller)
{
// Return if we have no pads
if (NumGoodPads == 0) return;
//DEBUG_LOG(WIIMOTE, "GetJoyState: Polling:%i NumPads:%i", SDLPolling, NumPads);
// Return if polling is off
if (!IsPolling) return;
// Update joyinfo handles. This is in case the Wiimote plugin has restarted SDL after a pad was conencted/disconnected
// so that the handles are updated. We don't need to run this this often. Once a second would be enough.
LocalSearchDevices(joyinfo, NumPads);
// Return if we have no pads
if (NumPads == 0) return;
// Read info
int NumButtons = SDL_JoystickNumButtons(_PadState.joy);
// Update the gamepad status
SDL_JoystickUpdate();
@@ -152,14 +263,13 @@ void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONT
}
#endif
/* Debugging
// Console::ClearScreen();
DEBUG_LOG(CONSOLE,
"Controller and handle: %i %i\n"
"Triggers:%i %i %i %i %i\n"
"Analog:%06i %06i \n",
/* Debugging
ConsoleListener* Console = LogManager::GetInstance()->getConsoleListener();
Console->ClearScreen();
Console->CustomLog(StringFromFormat(
"Controller: %i Handle: %i\n"
"Triggers: %i %i %i %i %i\n"
"Analog: %06i %06i \n",
controller, (int)_PadState.joy,
@@ -168,7 +278,8 @@ void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONT
_PadState.Axis.Tl, _PadState.Axis.Tr,
_PadState.Axis.Lx, _PadState.Axis.Ly
);*/
).c_str());
*/
}
@@ -21,6 +21,7 @@
#include <string>
#include "Common.h" // Common
#include "LogManager.h"
#include "Timer.h"
#include "pluginspecs_wiimote.h"
#include "StringUtil.h" // For ArrayToString
@@ -440,7 +441,7 @@ void SingleShake(u8 &_y, u8 &_z, int i)
void TiltWiimoteGamepad(float &Roll, float &Pitch)
{
// Return if we have no pads
if (NumGoodPads == 0) return;
if (NumPads == 0) return;
// This has to be changed if multiple Wiimotes are to be supported later
const int Page = 0;
+12 -8
View File
@@ -420,11 +420,13 @@ bool IsFocus()
HWND Parent = GetParent(RenderingWindow);
HWND TopLevel = GetParent(Parent);
// Allow updates when the config window is in focus to
HWND Config = NULL;
if (m_BasicConfigFrame)
Config = (HWND)m_BasicConfigFrame->GetHWND();
HWND Config = NULL, ConfigPad = NULL, ConfigRecording = NULL;
if (m_BasicConfigFrame) Config = (HWND)m_BasicConfigFrame->GetHWND();
if (m_PadConfigFrame) ConfigPad = (HWND)m_PadConfigFrame->GetHWND();
if (m_RecordingConfigFrame) ConfigRecording = (HWND)m_RecordingConfigFrame->GetHWND();
// Support both rendering to main window and not
if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == RenderingWindow || GetForegroundWindow() == Config)
if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == RenderingWindow || GetForegroundWindow() == Config
|| GetForegroundWindow() == ConfigPad || GetForegroundWindow() == ConfigRecording)
return true;
else
return false;
@@ -757,12 +759,14 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
// ---------------------------------------------
// Test the angles to x, y, z values formula by calculating the values back and forth
// -----------
/* //Console::ClearScreen();
/**/
ConsoleListener* Console = LogManager::GetInstance()->getConsoleListener();
Console->ClearScreen();
// Show a test of our calculations
WiiMoteEmu::TiltTest(data[4], data[5], data[6]);
u8 x, y, z;
WiiMoteEmu::Tilt(x, y, z);
WiiMoteEmu::TiltTest(x, y, z);*/
//u8 x, y, z;
//WiiMoteEmu::Tilt(x, y, z);
//WiiMoteEmu::TiltTest(x, y, z);
// -------------------------
// ---------------------------------------------
+1 -1
View File
@@ -35,7 +35,7 @@ int GetUpdateRate();
void InterruptDebugging(bool Emu, const void* _pData);
void ReadDebugging(bool Emu, const void* _pData, int Size);
bool IsFocus();
#define MAX_WIIMOTES 1
// Movement recording
#define RECORDING_ROWS 15
@@ -26,8 +26,6 @@
namespace WiiMoteReal
{
#define MAX_WIIMOTES 1
int Initialize();
void DoState(PointerWrap &p);
void Shutdown(void);
@@ -471,7 +471,7 @@
AdditionalDependencies="SDL.lib comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName)DF.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
AdditionalLibraryDirectories="..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
+40 -22
View File
@@ -46,6 +46,7 @@ Config::Config()
{
// Clear the memory
//memset(this, 0, sizeof(Config));
Loaded = false;
}
@@ -95,7 +96,7 @@ void DEBUG_QUIT()
void Config::Save(int Slot)
{
// If there are no good pads don't save
if (NumGoodPads == 0) return;
if (NumPads == 0) return;
// Load ini file
IniFile file;
@@ -127,22 +128,27 @@ void Config::Save(int Slot)
// Save the physical device ID
file.Set(SectionName.c_str(), "joy_id", PadMapping[i].ID);
file.Set(SectionName.c_str(), "joy_name", PadMapping[i].Name);
// ===================
// ==================================================================
// Joypad or slot specific settings
// -----------------
// Current joypad device ID: PadMapping[i].ID
// Current joypad name: joyinfo[PadMapping[i].ID].Name
// Current joypad device ID: PadMapping[i].ID
// Current joypad name: IDToName(PadMapping[i].ID])
if(g_Config.bSaveByID)
{
/* Save joypad specific settings. Check for "PadMapping[i].ID < SDL_NumJoysticks()" to
avoid reading a joyinfo that does't exist */
if((u32)PadMapping[i].ID >= joyinfo.size()) continue;
// Create a new section name after the joypad name
SectionName = joyinfo[PadMapping[i].ID].Name;
SectionName = IDToName(PadMapping[i].ID);
// Don't save a blank name
if (SectionName == "")
{
ERROR_LOG(PAD, "ID %i has no name, will not save", PadMapping[i].ID);
continue;
}
}
NOTICE_LOG(PAD, "Save settings for ID %i '%s' from PadMapping[%i]", PadMapping[i].ID, SectionName.c_str(), i);
file.Set(SectionName.c_str(), "l_shoulder", PadMapping[i].buttons[InputCommon::CTL_L_SHOULDER]);
file.Set(SectionName.c_str(), "r_shoulder", PadMapping[i].buttons[InputCommon::CTL_R_SHOULDER]);
@@ -180,8 +186,6 @@ void Config::Save(int Slot)
file.Set(SectionName.c_str(), "SquareToCircleC", PadMapping[i].bSquareToCircleC);
}
INFO_LOG(CONSOLE, "%i: Save: %i\n", 0, PadMapping[0].halfpress);
file.Save(FULL_CONFIG_DIR "nJoy.ini");
}
@@ -189,8 +193,7 @@ void Config::Save(int Slot)
// -----------------------
void Config::Load(bool ChangePad, bool ChangeSaveByID)
{
// If there are no good pads don't load
if (NumGoodPads == 0) return;
Loaded = true;
// Load file
IniFile file;
@@ -211,6 +214,9 @@ void Config::Load(bool ChangePad, bool ChangeSaveByID)
}
// =============
// If there are no good pads don't load anymore
if (NumPads == 0) return;
for (int i = 0; i < 4; i++)
{
std::string SectionName = StringFromFormat("PAD%i", i+1);
@@ -219,23 +225,32 @@ void Config::Load(bool ChangePad, bool ChangeSaveByID)
if (!ChangePad)
{
file.Get(SectionName.c_str(), "joy_id", &PadMapping[i].ID, 0);
file.Get(SectionName.c_str(), "joy_name", &PadMapping[i].Name, "");
}
// ==================================================================
// Joypad or slot specific settings
// -----------------
// Current joypad device ID: PadMapping[i].ID
// Current joypad name: joyinfo[PadMapping[i].ID].Name
if(g_Config.bSaveByID)
// Current joypad device ID: PadMapping[i].ID
// Current joypad name: IDToName(PadMapping[i].ID)
if (g_Config.bSaveByID)
{
// Prevent a crash from illegal access to joyinfo that will only have values for
// the current amount of connected pads
if((u32)PadMapping[i].ID >= joyinfo.size()) continue;
// Create a section name
SectionName = joyinfo[PadMapping[i].ID].Name;
SectionName = PadMapping[i].Name;
// Don't load settings for a non-connected device
if (!IsConnected(SectionName))
{
ERROR_LOG(PAD, "Slot %i: The device '%s' is not connected, will not load settings", SectionName.c_str());
continue;
}
// Don't load a blank ID
if (SectionName == "")
{
ERROR_LOG(PAD, "Slot %i has no device name, will not load settings", i);
continue;
}
}
file.Get(SectionName.c_str(), "l_shoulder", &PadMapping[i].buttons[InputCommon::CTL_L_SHOULDER], 4);
file.Get(SectionName.c_str(), "r_shoulder", &PadMapping[i].buttons[InputCommon::CTL_R_SHOULDER], 5);
file.Get(SectionName.c_str(), "a_button", &PadMapping[i].buttons[InputCommon::CTL_A_BUTTON], 0);
@@ -269,8 +284,11 @@ void Config::Load(bool ChangePad, bool ChangeSaveByID)
file.Get(SectionName.c_str(), "RadiusOnOffC", &Tmp, false); PadMapping[i].bRadiusOnOffC = Tmp;
file.Get(SectionName.c_str(), "DiagonalC", &PadMapping[i].SDiagonalC, "100%");
file.Get(SectionName.c_str(), "SquareToCircleC", &Tmp, false); PadMapping[i].bSquareToCircleC = Tmp;
NOTICE_LOG(PAD, "Slot %i: Load settings for ID %i '%s'", i, PadMapping[i].ID, SectionName.c_str());
}
INFO_LOG(CONSOLE, "%i: Load: %i\n", 0, PadMapping[0].halfpress);
//INFO_LOG(PAD, "%i: Load: %i\n", 0, PadMapping[0].halfpress);
}
+2 -1
View File
@@ -23,9 +23,10 @@ struct Config
Config();
void Load(bool ChangePad = false, bool ChangeSaveByID = false);
void Save(int Slot = -1);
bool Loaded;
int CheckForDuplicateJoypads(bool OK);
// General
// Settings
bool bShowAdvanced; // Only allow one of these
bool bSaveByID;
bool bCheckFocus;
@@ -1,4 +1,3 @@
// Project description
// -------------------
// Name: nJoy
@@ -32,14 +31,15 @@
// ---------
#include "ConfigBox.h"
#include "../nJoy.h"
#include "LogManager.h"
#include "Images/controller.xpm"
extern bool g_EmulatorRunning;
// Set PAD status
// --------------
void PADConfigDialognJoy::PadGetStatus()
{
void PADConfigDialognJoy::PadShowStatus()
{
// Return if it's not detected. The ID should never be less than zero here, it can only be that
// because of a manual ini file change, but we make that check anway.
if(PadMapping[notebookpage].ID < 0 || PadMapping[notebookpage].ID >= SDL_NumJoysticks())
@@ -51,7 +51,7 @@ void PADConfigDialognJoy::PadGetStatus()
}
// Get physical device status
int PhysicalDevice = PadMapping[notebookpage].ID;
int ID = PadMapping[notebookpage].ID;
int TriggerType = PadMapping[notebookpage].triggertype;
// Get original values
@@ -105,7 +105,6 @@ void PADConfigDialognJoy::PadGetStatus()
m_bmpDotOutC[notebookpage]->SetPosition(wxPoint(sub_x_out, sub_y_out));
///////////////////// Analog stick
// Triggers
// -----------------
@@ -143,84 +142,12 @@ void PADConfigDialognJoy::PadGetStatus()
///////////////////// Triggers
}
// Show the current pad status
// -----------------
std::string ShowStatus(int VirtualController)
{
// Save the physical device
int PhysicalDevice = PadMapping[VirtualController].ID;
// Make local shortcut
SDL_Joystick *joy = PadState[VirtualController].joy;
// Make shortcuts for all pads
SDL_Joystick *joy0 = PadState[0].joy;
SDL_Joystick *joy1 = PadState[1].joy;
SDL_Joystick *joy2 = PadState[2].joy;
SDL_Joystick *joy3 = PadState[3].joy;
// Temporary storage
std::string StrAxes, StrHats, StrBut;
int value;
// Get status
int Axes = joyinfo[PhysicalDevice].NumAxes;
int Balls = joyinfo[PhysicalDevice].NumBalls;
int Hats = joyinfo[PhysicalDevice].NumHats;
int Buttons = joyinfo[PhysicalDevice].NumButtons;
// Update the internal values
SDL_JoystickUpdate();
// Go through all axes and read out their values
for(int i = 0; i < Axes; i++)
{
value = SDL_JoystickGetAxis(joy, i);
StrAxes += StringFromFormat(" %i:%06i", i, value);
}
for(int i = 0;i < Hats; i++)
{
value = SDL_JoystickGetHat(joy, i);
StrHats += StringFromFormat(" %i:%i", i, value);
}
for(int i = 0;i < Buttons; i++)
{
value = SDL_JoystickGetButton(joy, i);
StrBut += StringFromFormat(" %i:%i", i+1, value);
}
return StringFromFormat(
"All pads:\n"
"ID: %i %i %i %i\n"
"Controllertype: %i %i %i %i\n"
"SquareToCircle: %i %i %i %i\n\n"
#ifdef _WIN32
"Handles: %i %i %i %i\n"
"XInput: %i %i %i\n"
#endif
"This pad:\n"
"Axes: %s\n"
"Hats: %s\n"
"But: %s\n"
"Device: Ax: %i Balls:%i Hats:%i But:%i",
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,
#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(),
Axes, Balls, Hats, Buttons
);
}
// Populate the advanced tab
// Update the advanced tab
// -----------------
void PADConfigDialognJoy::Update()
{
{
if (!IsPolling()) return;
// 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
@@ -228,17 +155,41 @@ void PADConfigDialognJoy::Update()
if (g_Config.bCheckFocus || IsFocus()) // && !g_EmulatorRunning)
{
for (int i = 0; (u32)i < joyinfo.size(); i++)
InputCommon::GetJoyState(PadState[i], PadMapping[i], i, joyinfo[PadMapping[i].ID].NumButtons);
InputCommon::GetJoyState(PadState[notebookpage], PadMapping[notebookpage]);
PadShowStatus();
}
// Show the current status in a window in the wxPanel
#ifdef SHOW_PAD_STATUS
m_pStatusBar->SetLabel(wxString::Format(
"%s", ShowStatus(notebookpage).c_str()
));
m_pStatusBar->SetLabel(wxString::FromAscii(InputCommon::ShowStatus(
notebookpage, m_Joyname[notebookpage]->GetSelection(),
PadMapping, PadState, joyinfo
).c_str()));
#endif
}
// Search for devices
void PADConfigDialognJoy::UpdateSlow()
{
if (!LiveUpdates) return;
// Search for connected devices and update dialog
int OldNumDIDevices = NumDIDevices;
NumDIDevices = InputCommon::SearchDIDevices();
// Update if a pad has been connected/disconnected. Todo: Add a better check that also takes into consideration the pad id
// and other things to better ensure that nothing has changed
//DEBUG_LOG(PAD, "Found %i devices", NumDIDevices);
//DEBUG_LOG(PAD, "UpdateSlow: %i %i", OldNumPads, NumPads);
if (OldNumDIDevices != NumDIDevices)
{
WARN_LOG(PAD, "\n---- %s ----", (NumDIDevices > OldNumDIDevices) ? "Pad connected" : "Pad disconnected");
LocalSearchDevicesReset(joyinfo, NumPads);
UpdateDeviceList();
// Enable controls again, if disabled
UpdateGUIAll();
}
}
// Populate the advanced tab
// -----------------
@@ -368,6 +319,5 @@ wxBitmap PADConfigDialognJoy::CreateBitmapArea(int Max, int Diagonal)
Points[7].x = (int)(-Diagonal * Adj + iAdj); Points[7].y = (int)(Diagonal * Adj + iAdj);
// Draw polygon
dc.DrawPolygon(8, Points);
return bitmap;
}
@@ -103,6 +103,7 @@ BEGIN_EVENT_TABLE(PADConfigDialognJoy,wxDialog)
EVT_BUTTON(IDB_ANALOG_SUB_Y, PADConfigDialognJoy::GetButtons)
#if wxUSE_TIMER
EVT_TIMER(IDTM_SLOW, PADConfigDialognJoy::OnSlowTimer)
EVT_TIMER(IDTM_CONSTANT, PADConfigDialognJoy::OnTimer)
EVT_TIMER(IDTM_BUTTON, PADConfigDialognJoy::OnButtonTimer)
#endif
@@ -112,26 +113,40 @@ PADConfigDialognJoy::PADConfigDialognJoy(wxWindow *parent, wxWindowID id, const
const wxPoint &position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style)
{
// Define values
// Initialize values
notebookpage = 0;
g_Pressed = 0;
Debugging = false;
g_Pressed = 0;
m_TCDebugging = NULL;
ControlsCreated = false;
// Settings
Debugging = false;
// Only tested in Windows
#ifdef _WIN32
LiveUpdates = true;
#else
LiveUpdates = false;
#endif
// Create controls
CreateGUIControls();
// Update GUI
UpdateGUIAll();
// Update device list
UpdateDeviceList();
#if wxUSE_TIMER
m_SlowTimer = new wxTimer(this, IDTM_SLOW);
m_ConstantTimer = new wxTimer(this, IDTM_CONSTANT);
m_ButtonMappingTimer = new wxTimer(this, IDTM_BUTTON);
// Reset values
GetButtonWaitingID = 0; GetButtonWaitingTimer = 0;
// Start the constant timer
int TimesPerSecond = 30;
m_ConstantTimer->Start( floor((double)(1000 / TimesPerSecond)) );
// Start timers
StartTimer();
#endif
// wxEVT_KEY_DOWN is blocked for enter, tab and the directional keys
@@ -148,6 +163,24 @@ PADConfigDialognJoy::~PADConfigDialognJoy()
#endif
}
void PADConfigDialognJoy::DoShow()
{
// Start timers
StartTimer();
// Show
ShowModal();
}
void PADConfigDialognJoy::StartTimer()
{
// Start the slow timer
double TimesPerSecond = 2;
m_SlowTimer->Start( floor((double)(1000.0 / TimesPerSecond)) );
// Start the constant timer
TimesPerSecond = 30;
m_ConstantTimer->Start( floor((double)(1000 / TimesPerSecond)) );
}
void PADConfigDialognJoy::OnKeyDown(wxKeyEvent& event)
{
g_Pressed = event.GetKeyCode();
@@ -160,7 +193,9 @@ void PADConfigDialognJoy::OnClose(wxCloseEvent& event)
event.Skip();
// Stop the timer
m_SlowTimer->Stop();
m_ConstantTimer->Stop();
m_ButtonMappingTimer->Stop();
// Close pads, unless we are running a game
if (!g_EmulatorRunning) Shutdown();
@@ -256,7 +291,7 @@ void PADConfigDialognJoy::DoSave(bool ChangePad, int Slot)
g_Config.Save(Slot);
// Now we can update the ID
PadMapping[notebookpage].ID = m_Joyname[notebookpage]->GetSelection();
UpdateID();
}
else
{
@@ -268,6 +303,21 @@ void PADConfigDialognJoy::DoSave(bool ChangePad, int Slot)
// Then change it back to ""
ToBlank();
}
void PADConfigDialognJoy::UpdateID()
{
INFO_LOG(PAD, "Slot %i: Changed PadMapping ID from %i to %i", notebookpage, PadMapping[notebookpage].ID, m_Joyname[notebookpage]->GetSelection());
PadMapping[notebookpage].ID = joyinfo.at(m_Joyname[notebookpage]->GetSelection()).ID;
PadMapping[notebookpage].Name = joyinfo.at(m_Joyname[notebookpage]->GetSelection()).Name;
// Update all handles
for(int i = 0; i < 4; i++)
{
if (PadMapping[i].Name == PadMapping[notebookpage].Name)
{
if (m_Joyname[i]->GetSelection() >= 0 && joyinfo.size() > m_Joyname[i]->GetSelection())
PadState[i].joy = joyinfo.at(m_Joyname[i]->GetSelection()).joy;
}
}
}
// On changing the SaveById option we update all pages
void PADConfigDialognJoy::OnSaveById()
@@ -290,11 +340,52 @@ void PADConfigDialognJoy::OnSaveById()
void PADConfigDialognJoy::DoChangeJoystick()
{
// Before changing the pad we save potential changes to the current pad (to support SaveByID)
WARN_LOG(PAD, "\n--- DoChangeJoystick ----");
WARN_LOG(PAD, "DoSave");
DoSave(true);
// Load the settings for the new Id
// Load the settings for the new ID
WARN_LOG(PAD, "Load");
g_Config.Load(true);
UpdateGUI(notebookpage); // Update the GUI
// Update the GUI
WARN_LOG(PAD, "UpdateGUI");
UpdateGUI(notebookpage);
WARN_LOG(PAD, "");
}
// Pads have been connected/disconnected
void PADConfigDialognJoy::UpdateDeviceList()
{
if (!ControlsCreated) return;
DEBUG_LOG(PAD, "UpdateDeviceList");
for (int i = 0; i < 4; i++)
{
// Save current selection
//std::string CurrentSel = m_Joyname[i]->GetValue().mb_str();
m_Joyname[i]->Clear();
// Search for devices and add them to the device list
if (NumPads > 0)
{
for (int j = 0; j < NumPads; j++)
m_Joyname[i]->Append(wxString::FromAscii(joyinfo.at(j).Name.c_str()));
// Set selection
//PanicAlert("%s", PadMapping[i].Name.c_str());
for (int j = 0; j < NumPads; j++)
{
if (joyinfo.at(j).Name == PadMapping[i].Name) m_Joyname[i]->SetSelection(j);
}
if (m_Joyname[i]->GetSelection() == -1) m_Joyname[i]->SetSelection(0);
// Load settings
DoChangeJoystick();
}
else
{
m_Joyname[i]->Append(wxString::FromAscii("<No Gamepad Detected>"));
m_Joyname[i]->SetSelection(0);
}
}
}
// Notebook page changed
@@ -303,7 +394,7 @@ void PADConfigDialognJoy::NotebookPageChanged(wxNotebookEvent& event)
// Save current settings now, don't wait for OK
if (ControlsCreated && !g_Config.bSaveByID) DoSave(false, notebookpage);
// Update the global variable
// Update the global variable
notebookpage = event.GetSelection();
// Update GUI
@@ -335,28 +426,28 @@ void PADConfigDialognJoy::ToBlank(bool ToBlank)
}
// Change settings
// Change settings for all slots that have this pad selected
// -----------------------
void PADConfigDialognJoy::SetButtonTextAll(int id, const char *text)
{
for (int i = 0; i < 4; i++)
{
// Safety check to avoid crash
if (joyinfo.size() > (u32)PadMapping[i].ID)
if (joyinfo[PadMapping[i].ID].Name == joyinfo[PadMapping[notebookpage].ID].Name)
SetButtonText(id, text, i);
if (IDToName(PadMapping[i].ID) == IDToName(PadMapping[notebookpage].ID))
{
SetButtonText(id, text, i);
DEBUG_LOG(PAD, "Updated button text for slot %i", i);
}
};
}
void PADConfigDialognJoy::SaveButtonMappingAll(int Slot)
{
for (int i = 0; i < 4; i++)
{
// This can occur when no gamepad is detected
if (joyinfo.size() > (u32)PadMapping[i].ID)
if (joyinfo[PadMapping[i].ID].Name == joyinfo[PadMapping[Slot].ID].Name)
SaveButtonMapping(i, false, Slot);
if (IDToName(PadMapping[i].ID) == IDToName(PadMapping[Slot].ID))
SaveButtonMapping(i, false, Slot);
}
}
// -----------------------
void PADConfigDialognJoy::UpdateGUIAll(int Slot)
{
@@ -368,10 +459,8 @@ void PADConfigDialognJoy::UpdateGUIAll(int Slot)
{
for (int i = 0; i < 4; i++)
{
// Safety check to avoid crash
if (joyinfo.size() > (u32)PadMapping[i].ID)
if (joyinfo[PadMapping[i].ID].Name == joyinfo[PadMapping[Slot].ID].Name)
UpdateGUI(i);
if (IDToName(PadMapping[i].ID) == IDToName(PadMapping[Slot].ID))
UpdateGUI(i);
}
}
}
@@ -438,8 +527,10 @@ void PADConfigDialognJoy::ChangeSettings( wxCommandEvent& event )
}
// Update all slots that use this device
if(g_Config.bSaveByID) SaveButtonMappingAll(notebookpage);
if(g_Config.bSaveByID) UpdateGUIAll(notebookpage);
//if(g_Config.bSaveByID)
SaveButtonMappingAll(notebookpage);
//if(g_Config.bSaveByID)
UpdateGUIAll(notebookpage);
}
@@ -447,12 +538,18 @@ void PADConfigDialognJoy::ChangeSettings( wxCommandEvent& event )
// Called from: CreateGUIControls(), ChangeControllertype()
void PADConfigDialognJoy::UpdateGUI(int _notebookpage)
{
DEBUG_LOG(PAD, "UpdateGUI for slot %i, %i pads connected", _notebookpage, NumPads);
// If there are no good pads disable the entire notebook
if (NumGoodPads == 0)
if (NumPads == 0)
{
m_Notebook->Enable(false);
return;
}
else
{
m_Notebook->Enable(true);
}
// Update the GUI from PadMapping[]
UpdateGUIButtonMapping(_notebookpage);
@@ -505,6 +602,8 @@ void PADConfigDialognJoy::UpdateGUI(int _notebookpage)
else m_CoBRadiusC[_notebookpage]->Enable(false);
if (PadMapping[_notebookpage].bSquareToCircleC) m_CoBDiagonalC[_notebookpage]->Enable(true);
else m_CoBDiagonalC[_notebookpage]->Enable(false);
DEBUG_LOG(PAD, "Main radius %s", PadMapping[_notebookpage].bRadiusOnOff ? "enabled" : "disabled");
}
// Repaint the background
@@ -565,24 +664,9 @@ void PADConfigDialognJoy::CreateGUIControls()
m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[3], wxT("Controller 4"));
// Define bitmap for EVT_PAINT
WxStaticBitmap1_BITMAP = wxBitmap(ConfigBox_WxStaticBitmap1_XPM);
// Search for devices and add them to the device list
wxArrayString arrayStringFor_Joyname; // The string array
if (NumGoodPads > 0)
{
for(int x = 0; (u32)x < joyinfo.size(); x++)
{
arrayStringFor_Joyname.Add(wxString::FromAscii(joyinfo[x].Name.c_str()));
}
}
else
{
arrayStringFor_Joyname.Add(wxString::FromAscii("<No Gamepad Detected>"));
}
// Populate the DPad type and Trigger type list
wxArrayString wxAS_DPadType;
wxAS_DPadType.Add(wxString::FromAscii(DPadType[InputCommon::CTL_DPAD_HAT]));
@@ -721,7 +805,7 @@ void PADConfigDialognJoy::CreateGUIControls()
// Populate Controller sizer
// Groups
#ifdef _WIN32
m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, arrayStringFor_Joyname[0], wxDefaultPosition, wxSize(476, 21), arrayStringFor_Joyname, wxCB_READONLY);
m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxDefaultPosition, wxSize(476, 21), 0, NULL, wxCB_READONLY);
#else
m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, arrayStringFor_Joyname[0], wxDefaultPosition, wxSize(450, 25), arrayStringFor_Joyname, 0, wxDefaultValidator, wxT("m_Joyname"));
#endif
@@ -954,9 +1038,6 @@ void PADConfigDialognJoy::CreateGUIControls()
// Show or hide it. We have to do this after we add it to its sizer
m_sMainRight[i]->Show(g_Config.bShowAdvanced);
// Update GUI
UpdateGUI(i);
} // end of loop
// Populate buttons sizer.
@@ -975,7 +1056,7 @@ void PADConfigDialognJoy::CreateGUIControls()
// Debugging
#ifdef SHOW_PAD_STATUS
m_pStatusBar = new wxStaticText(this, IDT_DEBUGGING, wxT("Debugging"), wxPoint(135, 100), wxDefaultSize);
m_pStatusBar = new wxStaticText(this, IDT_DEBUGGING, wxT("Debugging"), wxPoint(135, 100), wxSize(200, -1));
#endif
// Set window size
@@ -62,12 +62,17 @@ class PADConfigDialognJoy : public wxDialog
long style = wxDEFAULT_DIALOG_STYLE);
virtual ~PADConfigDialognJoy();
// Timers
#if wxUSE_TIMER
void OnSlowTimer(wxTimerEvent& WXUNUSED(event)) { UpdateSlow(); }
void OnTimer(wxTimerEvent& WXUNUSED(event)) { Update(); }
void OnButtonTimer(wxTimerEvent& WXUNUSED(event)) { DoGetButtons(GetButtonWaitingID); }
wxTimer *m_ConstantTimer, *m_ButtonMappingTimer;
wxTimer *m_SlowTimer, *m_ConstantTimer, *m_ButtonMappingTimer;
#endif
// Functions
void DoShow();
// Debugging
wxStaticText* m_pStatusBar, * m_pStatusBar2;
wxTextCtrl* m_TCDebugging;
@@ -195,7 +200,10 @@ class PADConfigDialognJoy : public wxDialog
*m_bmpSquare[4], *m_bmpDot[4], *m_bmpSquareOut[4], *m_bmpDotOut[4], *m_bmpAreaOut[4],
*m_bmpSquareC[4], *m_bmpDotC[4], *m_bmpSquareOutC[4], *m_bmpDotOutC[4], *m_bmpAreaOutC[4];
int notebookpage; bool ControlsCreated;
// Settings
int notebookpage;
bool ControlsCreated;
bool LiveUpdates;
private:
enum
@@ -233,7 +241,7 @@ class PADConfigDialognJoy : public wxDialog
IDT_TRIGGERS, IDCB_CHECKFOCUS, IDCB_FILTER_SETTINGS,
// Timers
IDTM_CONSTANT, IDTM_BUTTON,
IDTM_SLOW, IDTM_CONSTANT, IDTM_BUTTON,
// ==============================================
@@ -316,6 +324,8 @@ class PADConfigDialognJoy : public wxDialog
void OKClick(wxCommandEvent& event);
void CancelClick(wxCommandEvent& event);
void DoSave(bool ChangePad = false, int Slot = -1);
void UpdateID();
void StartTimer();
void DoChangeJoystick();
@@ -323,20 +333,22 @@ class PADConfigDialognJoy : public wxDialog
void ChangeSettings(wxCommandEvent& event);
void ComboChange(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);
void UpdateDeviceList();
void CreateGUIControls();
void CreateAdvancedControls(int i);
wxBitmap CreateBitmap();
wxBitmap CreateBitmapDot();
wxBitmap CreateBitmapArea(int,int);
void PadGetStatus();
void PadShowStatus();
void UpdateSlow();
void Update();
void UpdateGUIButtonMapping(int controller);
void SaveButtonMapping(int controller, bool DontChangeId = false, int FromSlot = -1);
void SaveButtonMappingAll(int Slot);
void UpdateGUIAll(int Slot);
void UpdateGUIAll(int Slot = -1);
void ToBlank(bool ToBlank = true);
void OnSaveById();
@@ -50,8 +50,11 @@ void PADConfigDialognJoy::UpdateGUIButtonMapping(int controller)
// http://wiki.wxwidgets.org/Converting_everything_to_and_from_wxString
wxString tmp;
// Assert
//if (!ControlsCreated[i]) return;
// Update selected gamepad
m_Joyname[controller]->SetSelection(PadMapping[controller].ID);
m_Joyname[controller]->SetValue(wxString::FromAscii(PadMapping[controller].Name.c_str()));
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();
@@ -99,7 +102,8 @@ void PADConfigDialognJoy::UpdateGUIButtonMapping(int controller)
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();
}
NOTICE_LOG(PAD, "Loaded from PadMapping[%i] to slot %i", controller, controller);
}
/* Populate the PadMapping array with the dialog items settings (for example
@@ -117,7 +121,21 @@ void PADConfigDialognJoy::SaveButtonMapping(int controller, bool DontChangeId, i
ToBlank(false);
// Set other settings
if(!DontChangeId) PadMapping[controller].ID = m_Joyname[FromSlot]->GetSelection();
if(!DontChangeId)
{
if (joyinfo.size() > m_Joyname[FromSlot]->GetSelection())
{
INFO_LOG(PAD, "%i: Changed PadMapping ID from %i to %i", controller, PadMapping[controller].ID, joyinfo.at(m_Joyname[FromSlot]->GetSelection()).ID);
PadMapping[controller].ID = joyinfo.at(m_Joyname[FromSlot]->GetSelection()).ID;
}
//else
// Assert
PadMapping[controller].Name = m_Joyname[FromSlot]->GetValue().mb_str();
}
NOTICE_LOG(PAD, "Saved PadMapping[%i] from slot %i", controller, FromSlot);
// Settings
PadMapping[controller].controllertype = m_ControlType[FromSlot]->GetSelection();
PadMapping[controller].triggertype = m_TriggerType[FromSlot]->GetSelection();
PadMapping[controller].deadzone = m_Deadzone[FromSlot]->GetSelection();
@@ -264,6 +282,13 @@ void PADConfigDialognJoy::GetButtons(wxCommandEvent& event)
void PADConfigDialognJoy::DoGetButtons(int GetId)
{
//INFO_LOG(PAD, "DoGetButtons: %i", GetId);
if (!SDLPolling || SDL_JoystickEventState(SDL_QUERY) == SDL_ENABLE) return;
// Turn off live updates because the change the joy handles
LiveUpdates = false;
// =============================================
// Collect the starting values
// ----------------
@@ -280,7 +305,7 @@ void PADConfigDialognJoy::DoGetButtons(int GetId)
int Axes = SDL_JoystickNumAxes(joy);
int Hats = SDL_JoystickNumHats(joy);
INFO_LOG(CONSOLE, "PadID: %i Axes: %i\n", PadID, joyinfo[PadID].NumAxes, joyinfo[PadID].joy);
//NOTICE_LOG(PAD, "PadID: %i Axes: %i Handle: %i\n", PadID, joyinfo[PadID].NumAxes, joyinfo[PadID].joy);
// Get the controller and trigger type
int ControllerType = PadMapping[Controller].controllertype;
@@ -343,6 +368,8 @@ void PADConfigDialognJoy::DoGetButtons(int GetId)
#if wxUSE_TIMER
m_ButtonMappingTimer->Start( floor((double)(1000 / TimesPerSecond)) );
#endif
//INFO_LOG(PAD, "Timer started");
}
// ===============================================
@@ -353,7 +380,7 @@ void PADConfigDialognJoy::DoGetButtons(int GetId)
else
{
InputCommon::GetButton(
joy, PadID, Buttons, Axes, Hats,
joy, PadID,
g_Pressed, value, type, pressed, Succeed, Stop,
LeftRight, Axis, XInput, Button, Hat, NoTriggerFilter);
}
@@ -368,7 +395,7 @@ void PADConfigDialognJoy::DoGetButtons(int GetId)
GetButtonWaitingTimer++;
// This is run every second
if(GetButtonWaitingTimer % TimesPerSecond == 0)
if (GetButtonWaitingTimer % TimesPerSecond == 0)
{
// Current time
int TmpTime = Seconds - (GetButtonWaitingTimer / TimesPerSecond);
@@ -379,7 +406,7 @@ void PADConfigDialognJoy::DoGetButtons(int GetId)
}
// Time's up
if( (GetButtonWaitingTimer / TimesPerSecond) >= Seconds )
if ( (GetButtonWaitingTimer / TimesPerSecond) >= Seconds )
{
Stop = true;
// Leave a blank mapping
@@ -387,8 +414,10 @@ void PADConfigDialognJoy::DoGetButtons(int GetId)
}
// If we got a button
if(Succeed)
if (Succeed)
{
//INFO_LOG(PAD, "Button mapping succeeded: %i", pressed);
Stop = true;
// Write the number of the pressed button to the text box
sprintf(format, "%d", pressed);
@@ -396,10 +425,12 @@ void PADConfigDialognJoy::DoGetButtons(int GetId)
}
// Stop the timer
if(Stop)
if (Stop)
{
m_ButtonMappingTimer->Stop();
GetButtonWaitingTimer = 0;
LiveUpdates = true;
//INFO_LOG(PAD, "Timer stopped");
/* Update the button mapping for all slots that use this device. (It doesn't make sense to have several slots
controlled by the same device, but several DirectInput instances of different but identical devices may possible
+139 -28
View File
@@ -48,7 +48,8 @@ std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
InputCommon::CONTROLLER_STATE PadState[4];
InputCommon::CONTROLLER_MAPPING PadMapping[4];
bool g_EmulatorRunning = false;
int NumPads = 0, NumGoodPads = 0, LastPad = 0;
bool SDLPolling = true;
int NumPads = 0, NumDIDevices = 0, LastPad = 0;
#ifdef _WIN32
HWND m_hWnd = NULL, m_hConsole = NULL; // Handle to window
#endif
@@ -154,11 +155,9 @@ void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
// ------------------
void DllConfig(HWND _hParent)
{
// Init Joystick + Haptic (force feedback) subsystem on SDL 1.3
// Populate joyinfo for all attached devices
Search_Devices(joyinfo, NumPads, NumGoodPads);
g_Config.Load(); // load settings
LocalSearchDevices(joyinfo, NumPads);
//g_Config.Load(); // load settings
#if defined(HAVE_WX) && HAVE_WX
if (!m_ConfigFrame)
@@ -168,9 +167,9 @@ void DllConfig(HWND _hParent)
// Only allow one open at a time
if (!m_ConfigFrame->IsShown())
m_ConfigFrame->ShowModal();
m_ConfigFrame->DoShow();
else
m_ConfigFrame->Hide();
m_ConfigFrame->Hide();
#endif
}
@@ -194,7 +193,7 @@ void Initialize(void *init)
#endif
// Populate joyinfo for all attached devices
Search_Devices(joyinfo, NumPads, NumGoodPads);
LocalSearchDevices(joyinfo, NumPads);
}
// Shutdown PAD (stop emulation)
@@ -221,18 +220,16 @@ void Shutdown()
for (int i = 0; i < 4; i++)
{
if (joyinfo.size() > (u32)PadMapping[i].ID)
if (joyinfo.at(PadMapping[i].ID).Good)
if(SDL_JoystickOpened(PadMapping[i].ID))
{
SDL_JoystickClose(PadState[i].joy);
PadState[i].joy = NULL;
}
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
SDL_Quit();
@@ -283,6 +280,12 @@ void DoState(unsigned char **ptr, int mode)
// Function: Gives the current pad status to the Core
void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
{
if (!IsPolling()) return;
// Update joyinfo handles. This is in case the Wiimote plugin has restarted SDL after a pad was conencted/disconnected
// so that the handles are updated.
LocalSearchDevices(joyinfo, NumPads);
// Check if the pad is avaliable, currently we don't disable pads just because they are
// disconnected
if (!PadState[_numPAD].joy) return;
@@ -292,7 +295,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// 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);
GetJoyState(PadState[_numPAD], PadMapping[_numPAD]);
// Get type
int TriggerType = PadMapping[_numPAD].triggertype;
@@ -439,29 +442,137 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// Search for SDL devices
// ----------------
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
{
bool Success = InputCommon::SearchDevices(_joyinfo, _NumPads, _NumGoodPads);
// Warn the user if no gamepads are detected
if (_NumGoodPads == 0 && g_EmulatorRunning)
bool LocalSearchDevices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads)
{
// Turn off device polling while searching
EnablePolling(false);
//DEBUG_LOG(PAD, "LocalSearchDevices");
bool Success = InputCommon::SearchDevices(_joyinfo, _NumPads);
DoLocalSearchDevices(_joyinfo, _NumPads);
EnablePolling(true);
return Success;
}
bool LocalSearchDevicesReset(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads)
{
//DEBUG_LOG(PAD, "LocalSearchDevicesUpdate: %i", IsPolling());
bool Success = InputCommon::SearchDevicesReset(_joyinfo, _NumPads);
DoLocalSearchDevices(_joyinfo, _NumPads);
return Success;
}
bool DoLocalSearchDevices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads)
{
// Don't warn the user if no gamepads are detected. If the pad doesn't respond he will open the configuration and fix it.
// Also, if he's using a Wii game he may not care that the gamepad is turned off.
if (_NumPads == 0 && g_EmulatorRunning)
{
PanicAlert("nJoy: No Gamepad Detected");
//PanicAlert("nJoy: No Gamepad Detected");
return false;
}
// Load PadMapping[] etc
g_Config.Load();
// Load the first time
if (!g_Config.Loaded) g_Config.Load();
// Update the PadState[].joy handle
for (int i = 0; i < 4; i++)
{
if (joyinfo.size() > (u32)PadMapping[i].ID)
if(joyinfo.at(PadMapping[i].ID).Good)
PadState[i].joy = SDL_JoystickOpen(PadMapping[i].ID);
for (int j = 0; j < joyinfo.size(); j++)
{
if (joyinfo.at(j).Name == PadMapping[i].Name)
{
PadState[i].joy = joyinfo.at(j).joy;
//DEBUG_LOG(PAD, "Slot %i: %s", i, joyinfo.at(j).Name.c_str());
}
}
}
return Success;
return true;
}
// Is the device connected?
// ----------------
bool IsConnected(std::string Name)
{
for (int i = 0; i < joyinfo.size(); i++)
{
//DEBUG_LOG(PAD, "IDToName: ID %i id %i %s", ID, i, joyinfo.at(i).Name.c_str());
if (joyinfo.at(i).Name == Name)
return true;
}
}
// Earlier versions of SDL could crash if SDL functions were called during SDL_Quit/SDL_Init. I could not get
// such a crash in the new version even with frequent SDL_Quit/SDL_Init so thse functions are disabled now.
// ----------------
bool IsPolling()
{
return true;
/*
if (!SDLPolling || SDL_JoystickEventState(SDL_QUERY) == SDL_ENABLE)
return false;
else
return true;
*/
}
void EnablePolling(bool Enable)
{
/*
if (Enable)
{
SDLPolling = true;
SDL_JoystickEventState(SDL_IGNORE);
}
else
{
SDLPolling = false;
SDL_JoystickEventState(SDL_ENABLE);
}
*/
}
// ID to Name
// ----------------
std::string IDToName(int ID)
{
for (int i = 0; i < joyinfo.size(); i++)
{
//DEBUG_LOG(PAD, "IDToName: ID %i id %i %s", ID, i, joyinfo.at(i).Name.c_str());
if (joyinfo.at(i).ID == ID)
return joyinfo.at(i).Name;
}
return "";
}
// ID to id - Get the gamepad id from a device ID (the ids will be all or some of the IDs)
// ----------------
int IDToid(int ID)
{
for (int i = 0; i < joyinfo.size(); i++)
{
if (joyinfo.at(i).ID == ID)
return i;
}
if (joyinfo.size() > 0)
{
ERROR_LOG(PAD, "IDToid error");
return 0;
}
else
{
PanicAlert("Error in IDToid. The plugin may crash.");
return -1;
}
}
+12 -2
View File
@@ -95,13 +95,23 @@
#ifdef _WIN32
extern HWND m_hWnd, m_hConsole; // Handle to window
#endif
extern int NumPads, NumGoodPads, LastPad; // Number of goods pads
extern int NumPads, NumDIDevices, LastPad; // Number of pads
extern bool SDLPolling;
#endif
// Custom Functions
// ----------------
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads);
bool LocalSearchDevices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads);
bool LocalSearchDevicesReset(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads);
bool DoLocalSearchDevices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads);
int SearchDIDevices();
bool IsConnected(std::string Name);
bool IsPolling();
void EnablePolling(bool Enable);
std::string IDToName(int ID);
bool IsConnected(std::string Name);
int IDToid(int ID);
void DEBUG_INIT();
void DEBUG_QUIT();
bool IsFocus();