1. Circumvent the IDirectInputDevice2::SetDataFormat() error when opening the configuration window to.

2. Fixed the Allow out of focus input option again

3. Allow changing of the mapped pads while a game is running

4. Prevented crashes or problems from any combination of having the configuration window open when a game is started or stopped

5. Fixed a crash that would occur after nJoy was started with a connected pad, then stopped, and all pads disconnected, then started again

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2215 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson
2009-02-11 10:30:02 +00:00
parent 5ba51ed789
commit 68f39cb287
18 changed files with 271 additions and 136 deletions

View File

@ -136,7 +136,7 @@ void Config::Save(int Slot)
{
/* Save joypad specific settings. Check for "PadMapping[i].ID < SDL_NumJoysticks()" to
avoid reading a joyinfo that does't exist */
if(PadMapping[i].ID >= SDL_NumJoysticks()) continue;
if(PadMapping[i].ID >= joyinfo.size()) continue;
// Create a new section name after the joypad name
SectionName = joyinfo[PadMapping[i].ID].Name;
@ -175,7 +175,7 @@ void Config::Save(int Slot)
//if(m_frame) m_frame->LogMsg("Saved: %s %i\n", SectionName.c_str(), PadMapping[i].triggertype);
}
//Console::Print("%i: Save: %i\n", 0, PadMapping[0].halfpress);
Console::Print("%i: Save: %i\n", 0, PadMapping[0].halfpress);
file.Save("nJoy.ini");
}
@ -224,8 +224,8 @@ void Config::Load(bool ChangePad, bool ChangeSaveByID)
if(g_Config.bSaveByID)
{
/* Prevent a crash from illegal access to joyinfo that will only have values for
the current amount of connected PadMapping */
if(PadMapping[i].ID >= SDL_NumJoysticks()) continue;
the current amount of connected pads */
if(PadMapping[i].ID >= joyinfo.size()) continue;
// Create a section name
SectionName = joyinfo[PadMapping[i].ID].Name;
@ -263,6 +263,6 @@ void Config::Load(bool ChangePad, bool ChangeSaveByID)
//if(m_frame) m_frame->LogMsg("%i: Enabled: %i\n", i, PadMapping[i].buttons[CTL_X_BUTTON]);
}
//Console::Print("%i: Load: %i\n", 0, PadMapping[0].halfpress);
Console::Print("%i: Load: %i\n", 0, PadMapping[0].halfpress);
}

View File

@ -70,11 +70,6 @@ void ConfigBox::PadGetStatus()
int PhysicalDevice = PadMapping[notebookpage].ID;
int TriggerType = PadMapping[notebookpage].triggertype;
// Check that Dolphin is in focus, otherwise don't update the pad status
if (!g_Config.bCheckFocus && IsFocus())
InputCommon::GetJoyState(PadState[notebookpage], PadMapping[notebookpage], notebookpage, joyinfo[PadMapping[notebookpage].ID].NumButtons);
//////////////////////////////////////
// Analog stick
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@ -220,13 +215,17 @@ std::string ShowStatus(int VirtualController)
return StringFromFormat(
//"Version: %i.%i.%i\n"
"All pads:\n"
"Enabled: %i %i %i %i\n"
"ID: %i %i %i %i\n"
"Controllertype: %i %i %i %i\n"
"SquareToCircle: %i %i %i %i\n\n"
"Handles: %p %p %p %p\n"
"SquareToCircle: %i %i %i %i\n\n"
#ifdef _WIN32
"Handles: %i %i %i %i\n"
"XInput: %i %i %i\n"
#endif
"XInput: %i %i %i\n"
"This pad:\n"
"Axes: %s\n"
"Hats: %s\n"
"But: %s\n"
@ -236,10 +235,9 @@ std::string ShowStatus(int VirtualController)
PadMapping[0].ID, PadMapping[1].ID, PadMapping[2].ID, PadMapping[3].ID,
PadMapping[0].controllertype, PadMapping[1].controllertype, PadMapping[2].controllertype, PadMapping[3].controllertype,
PadMapping[0].bSquareToCircle, PadMapping[1].bSquareToCircle, PadMapping[2].bSquareToCircle, PadMapping[3].bSquareToCircle,
joy0, joy1, joy2, joy3,
//PadState[PadMapping[0].ID].joy, PadState[PadMapping[1].ID].joy, PadState[PadMapping[2].ID].joy, PadState[PadMapping[3].ID].joy,
#ifdef _WIN32
joy0, joy1, joy2, joy3,
//PadState[PadMapping[0].ID].joy, PadState[PadMapping[1].ID].joy, PadState[PadMapping[2].ID].joy, PadState[PadMapping[3].ID].joy,
XInput::IsConnected(0), XInput::GetXI(0, InputCommon::XI_TRIGGER_L), XInput::GetXI(0, InputCommon::XI_TRIGGER_R),
#endif
StrAxes.c_str(), StrHats.c_str(), StrBut.c_str(),
@ -251,8 +249,17 @@ std::string ShowStatus(int VirtualController)
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ConfigBox::Update()
{
// Show the current status
/**/
// Check that Dolphin is in focus, otherwise don't update the pad status
/* If the emulator is running and unpaused GetJoyState() is run a little more often than needed,
but I allow that since it can confuse the user if the input status in the configuration window
is not update when the emulator is paused. */
if (g_Config.bCheckFocus || IsFocus()) // && !g_EmulatorRunning)
{
for (int i = 0; i < joyinfo.size(); i++)
InputCommon::GetJoyState(PadState[i], PadMapping[i], i, joyinfo[PadMapping[i].ID].NumButtons);
}
// Show the current status in a window in the wxPanel
#ifdef SHOW_PAD_STATUS
m_pStatusBar->SetLabel(wxString::Format(
"%s", ShowStatus(notebookpage).c_str()

View File

@ -159,10 +159,16 @@ void ConfigBox::OnKeyDown(wxKeyEvent& event)
// Close window
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ConfigBox::OnClose(wxCloseEvent& /*event*/)
void ConfigBox::OnClose(wxCloseEvent& event)
{
EndModal(0);
if(!g_EmulatorRunning) Shutdown(); // Close pads, unless we are running a game
// Allow wxWidgets to close the window
event.Skip();
// Stop the timer
m_ConstantTimer->Stop();
// Close pads, unless we are running a game
if(!g_EmulatorRunning) Shutdown();
}
// Call about dialog
@ -977,9 +983,9 @@ void ConfigBox::CreateGUIControls()
// Don't allow these changes when running
if(g_EmulatorRunning)
{
m_Joyname[i]->Enable(false);
//m_Joyname[i]->Enable(false);
m_Joyattach[i]->Enable(false);
m_ControlType[i]->Enable(false);
//m_ControlType[i]->Enable(false);
}
// Update GUI

View File

@ -88,8 +88,10 @@ 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;
HWND m_hWnd; // Handle to window
int NumPads = 0, NumGoodPads = 0, LastPad = 0;
#ifdef _WIN32
HWND m_hWnd = NULL, m_hConsole = NULL; // Handle to window
#endif
SPADInitialize *g_PADInitialize = NULL;
// TODO: fix this dirty hack to stop missing symbols
@ -187,28 +189,28 @@ void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals) {}
void DllConfig(HWND _hParent)
{
// Debugging
//Console::Open();
#ifdef SHOW_PAD_STATUS
Console::Open(100);
m_hConsole = Console::GetHwnd();
#endif
#ifdef _WIN32
// Start the pads so we can use them in the configuration and advanced controls
if(!g_EmulatorRunning)
{
Search_Devices(joyinfo, NumPads, NumGoodPads); // Populate joyinfo for all attached devices
// Check if a DirectInput error occured
if(ReloadDLL())
{
PostMessage(_hParent, WM_USER, NJOY_RELOAD, 0);
return;
}
}
m_frame = new ConfigBox(NULL);
m_frame->ShowModal();
m_frame->Show();
/* Check if any of the pads failed to open. In Windows there is a strange "IDirectInputDevice2::
SetDataFormat() DirectX error -2147024809" after a few Open and Close */
if ( (PadMapping[0].enabled && PadState[0].joy == NULL)
|| (PadMapping[1].enabled && PadState[1].joy == NULL)
|| (PadMapping[2].enabled && PadState[2].joy == NULL)
|| (PadMapping[3].enabled && PadState[3].joy == NULL))
{
//PostMessage(_hParent, 25, 0, 0);
Console::Print("%s\n", SDL_GetError());
}
#else
if (SDL_Init(SDL_INIT_JOYSTICK ) < 0)
{
@ -238,7 +240,10 @@ void DllDebugger(HWND _hParent, bool Show) {}
void Initialize(void *init)
{
// Debugging
//Console::Open();
#ifdef SHOW_PAD_STATUS
Console::Open(100);
m_hConsole = Console::GetHwnd();
#endif
Console::Print("Initialize: %i\n", SDL_WasInit(0));
g_PADInitialize = (SPADInitialize*)init;
g_EmulatorRunning = true;
@ -251,18 +256,11 @@ void Initialize(void *init)
m_hWnd = (HWND)g_PADInitialize->hWnd;
#endif
Search_Devices(joyinfo, NumPads, NumGoodPads); // Populate joyinfo for all attached devices
// Populate joyinfo for all attached devices if the configuration window is not already open
if(!m_frame) Search_Devices(joyinfo, NumPads, NumGoodPads);
/* Check if any of the pads failed to open. In Windows there is a strange "IDirectInputDevice2::
SetDataFormat() DirectX error -2147024809" after a few Open and Close */
if ( (PadMapping[0].enabled && PadState[0].joy == NULL)
|| (PadMapping[1].enabled && PadState[1].joy == NULL)
|| (PadMapping[2].enabled && PadState[2].joy == NULL)
|| (PadMapping[3].enabled && PadState[3].joy == NULL))
{
g_PADInitialize->padNumber = -1;
Console::Print("%s\n", SDL_GetError());
}
// Check if a DirectInput error occured
if(ReloadDLL()) g_PADInitialize->padNumber = -1;
}
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
@ -299,27 +297,40 @@ void Shutdown()
{
Console::Print("Shutdown: %i\n", SDL_WasInit(0));
// Always change this variable
g_EmulatorRunning = false;
// Don't shutdown if the configuration window is still showing
if (m_frame) return;
/* Close all devices carefully. We must check that we are not accessing any undefined
vector elements or any bad devices */
for (int i = 0; i < 4; i++)
{
if (PadMapping[i].enabled && joyinfo.size() > PadMapping[i].ID)
if (joyinfo.at(PadMapping[i].ID).Good)
if(SDL_JoystickOpened(PadMapping[i].ID)) SDL_JoystickClose(PadState[i].joy);
if(SDL_JoystickOpened(PadMapping[i].ID))
{
SDL_JoystickClose(PadState[i].joy);
PadState[i].joy = NULL;
}
}
// Clear the physical device info
joyinfo.clear();
NumPads = 0;
NumGoodPads = 0;
// Finally close SDL
if (SDL_WasInit(0)) SDL_Quit();
// Remove the pointer to the initialize data
g_PADInitialize = NULL;
#ifdef _DEBUG
DEBUG_QUIT();
#endif
g_EmulatorRunning = false;
#ifdef _WIN32
#ifdef USE_RUMBLE_DINPUT_HACK
FreeDirectInput();
@ -376,7 +387,7 @@ unsigned int PAD_GetAttachedPads()
if (PadMapping[2].enabled) connected |= 4;
if (PadMapping[3].enabled) connected |= 8;
//Console::Print("PAD_GetAttachedPads: %i %i %i\n", PadMapping[0].enabled, PadMapping[1].enabled, PadMapping[2].enabled, PadMapping[3].enabled);
//Console::Print("PAD_GetAttachedPads: %i %i %i %i\n", PadMapping[0].enabled, PadMapping[1].enabled, PadMapping[2].enabled, PadMapping[3].enabled);
return connected;
}
@ -388,16 +399,17 @@ unsigned int PAD_GetAttachedPads()
// Function: Gives the current pad status to the Core
void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
{
//Console::Print("%i %i %i\n", _numPAD, PadMapping[_numPAD].enabled, PadState[_numPAD].joy);
//Console::Print("PAD_GetStatus(): %i %i %i\n", _numPAD, PadMapping[_numPAD].enabled, PadState[_numPAD].joy);
// Check if the pad is enabled
/* Check if the pad is enabled and avaliable, currently we don't disable pads just because they are
disconnected */
if (!PadMapping[_numPAD].enabled || !PadState[_numPAD].joy) return;
// Clear pad status
memset(_pPADStatus, 0, sizeof(SPADStatus));
// Check that Dolphin is in focus, otherwise don't update the pad status
if (!g_Config.bCheckFocus && IsFocus())
if (g_Config.bCheckFocus || IsFocus())
GetJoyState(PadState[_numPAD], PadMapping[_numPAD], _numPAD, joyinfo[PadMapping[_numPAD].ID].NumButtons);
// Get type
@ -525,53 +537,81 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// Use rumble
Pad_Use_Rumble(_numPAD, _pPADStatus);
/* Debugging
if(_numPAD == 1)
{
Console::ClearScreen();
Console::Print(
"Pad %i: %i %i\n"
"State: L:%i R:%i HalfPress:%i\n"
"Trigger type: %s StatusLeft:%04x StatusRight:%04x TriggerLeft:%04x TriggerRight:%04x TriggerValue:%i\n"
"Buttons: %i X:%i\n"
"D-Pad type: %s L:%i R:%i U:%i D:%i",
// Debugging
/*
// Show the status of all connected pads
if ((LastPad == 0 && _numPAD == 0) || _numPAD < LastPad) Console::ClearScreen();
LastPad = _numPAD;
Console::Print(
"Pad | Number:%i Enabled:%i Handle:%i\n"
"Trigger | StatusLeft:%04x StatusRight:%04x TriggerLeft:%04x TriggerRight:%04x TriggerValue:%i\n"
"Buttons | Overall:%i X:%i\n"
"======================================================\n",
_numPAD, PadMapping[_numPAD].enabled, PadState[_numPAD].joy,
_numPAD, PadMapping[_numPAD].enabled, PadState[_numPAD].joy,
PadState[_numPAD].buttons[CTL_L_SHOULDER], PadState[_numPAD].buttons[CTL_R_SHOULDER], PadState[_numPAD].halfpress,
PadState[_numPAD].buttons[InputCommon::CTL_L_SHOULDER], PadState[_numPAD].buttons[InputCommon::CTL_R_SHOULDER], PadState[_numPAD].halfpress,
(PadMapping[_numPAD].triggertype ? "CTL_TRIGGER_XINPUT" : "CTL_TRIGGER_SDL"),
_pPADStatus->triggerLeft, _pPADStatus->triggerRight, TriggerLeft, TriggerRight, TriggerValue,
(PadMapping[_numPAD].triggertype ? "CTL_TRIGGER_XINPUT" : "CTL_TRIGGER_SDL"),
_pPADStatus->triggerLeft, _pPADStatus->triggerRight, TriggerLeft, TriggerRight, TriggerValue,
_pPADStatus->button, PadState[_numPAD].buttons[CTL_X_BUTTON],
(PadMapping[_numPAD].controllertype ? "CTL_DPAD_CUSTOM" : "CTL_DPAD_HAT"),
0, 0, 0, 0
);
}*/
_pPADStatus->button, PadState[_numPAD].buttons[InputCommon::CTL_X_BUTTON]
);
*/
}
///////////////////////////////////////////////// Spec functions
//******************************************************************************
// Supporting functions
//******************************************************************************
//////////////////////////////////////////////////////////////////////////////////////////
/* Check if any of the pads failed to open. In Windows there is a strange "IDirectInputDevice2::
SetDataFormat() DirectX error -2147024809" after exactly four SDL_Init() and SDL_Quit() */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool ReloadDLL()
{
if ( (PadMapping[0].enabled && PadState[0].joy == NULL)
|| (PadMapping[1].enabled && PadState[1].joy == NULL)
|| (PadMapping[2].enabled && PadState[2].joy == NULL)
|| (PadMapping[3].enabled && PadState[3].joy == NULL))
{
// Check if it was an error and not just no pads connected
std::string StrError = SDL_GetError();
if (StrError.find("IDirectInputDevice2") != std::string::npos)
{
// Clear the physical device info
joyinfo.clear();
NumPads = 0;
NumGoodPads = 0;
// Close SDL
if (SDL_WasInit(0)) SDL_Quit();
// Log message
Console::Print("Error: %s\n", StrError.c_str());
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Check if Dolphin is in focus
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool IsFocus()
{
return true;
#ifdef _WIN32
HWND RenderingWindow = NULL; if (g_PADInitialize) RenderingWindow = g_PADInitialize->hWnd;
HWND Parent = GetParent(RenderingWindow);
HWND TopLevel = GetParent(Parent);
HWND Config = NULL; if (m_frame) Config = (HWND)m_frame->GetHWND();
// Support both rendering to main window and not
if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == RenderingWindow || GetForegroundWindow() == Config)
// Support both rendering to main window and not, and the config and eventual console window
if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == RenderingWindow || GetForegroundWindow() == Config || GetForegroundWindow() == m_hConsole)
return true;
else
return false;

View File

@ -30,14 +30,15 @@
//////////////////////////////////////////////////////////////////////////////////////////
#ifndef __NJOY_h__
#define __NJOY_h__
//////////////////////////////////////////////////////////////////////////////////////////
// Settings
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Set this if you want to use the rumble 'hack' for controller one
//#define USE_RUMBLE_DINPUT_HACK
// Show a status window with the detected axes, buttons and so on
//#define SHOW_PAD_STATUS
//////////////////////////
@ -125,8 +126,10 @@ extern std::vector<u8> Keys;
extern std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
extern InputCommon::CONTROLLER_STATE PadState[4];
extern InputCommon::CONTROLLER_MAPPING PadMapping[4];
extern HWND m_hWnd; // Handle to window
extern int NumPads, NumGoodPads; // Number of goods pads
#ifdef _WIN32
extern HWND m_hWnd, m_hConsole; // Handle to window
#endif
extern int NumPads, NumGoodPads, LastPad; // Number of goods pads
#endif
@ -137,8 +140,12 @@ bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_N
void DEBUG_INIT();
void DEBUG_QUIT();
bool IsFocus();
bool ReloadDLL();
void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus); // Rumble
//void SaveConfig();
//void LoadConfig();
#endif __NJOY_h__