attempt to fix the main window closing from r5056. i'm not sure how this affects window deletion tho.

apply eol-style native to GCPad, pretty annoying to break patches and stuff

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5059 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
j4ck.fr0st 2010-02-14 16:33:53 +00:00
parent dc7029e7f4
commit cd321feb83
13 changed files with 3460 additions and 3456 deletions

View File

@ -193,6 +193,7 @@ void DllConfig(HWND _hParent)
m_ConfigFrame->ShowModal(); m_ConfigFrame->ShowModal();
delete m_ConfigFrame; delete m_ConfigFrame;
frame->SetHWND(NULL);
delete frame; delete frame;
m_ConfigFrame = 0; m_ConfigFrame = 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,261 +1,261 @@
// Project description // Project description
// ------------------- // -------------------
// Name: nJoy // Name: nJoy
// Description: A Dolphin Compatible Input Plugin // Description: A Dolphin Compatible Input Plugin
// //
// Author: Falcon4ever (nJoy@falcon4ever.com) // Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net // Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// //
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <iostream> #include <iostream>
#include "Common.h" #include "Common.h"
#include "IniFile.h" #include "IniFile.h"
#include "Config.h" #include "Config.h"
#include "GCPad.h" #include "GCPad.h"
#include "FileUtil.h" #include "FileUtil.h"
static const char* gcControlNames[] = static const char* gcControlNames[] =
{ {
"Button_A", "Button_A",
"Button_B", "Button_B",
"Button_X", "Button_X",
"Button_Y", "Button_Y",
"Button_Z", "Button_Z",
"Button_Start", "Button_Start",
"DPad_Up", "DPad_Up",
"DPad_Down", "DPad_Down",
"DPad_Left", "DPad_Left",
"DPad_Right", "DPad_Right",
"Stick_Up", "Stick_Up",
"Stick_Down", "Stick_Down",
"Stick_Left", "Stick_Left",
"Stick_Right", "Stick_Right",
"Stick_Semi", "Stick_Semi",
"CStick_Up", "CStick_Up",
"CStick_Down", "CStick_Down",
"CStick_Left", "CStick_Left",
"CStick_Right", "CStick_Right",
"CStick_Semi", "CStick_Semi",
"Shoulder_L", "Shoulder_L",
"Shoulder_R", "Shoulder_R",
"Shoulder_Semi_L", "Shoulder_Semi_L",
"Shoulder_Semi_R", "Shoulder_Semi_R",
}; };
static const int gcDefaultControls[] = static const int gcDefaultControls[] =
#ifdef _WIN32 #ifdef _WIN32
{ {
'X', 'X',
'Z', 'Z',
'C', 'C',
'S', 'S',
'D', 'D',
VK_RETURN, VK_RETURN,
'T', 'T',
'G', 'G',
'F', 'F',
'H', 'H',
VK_UP, VK_UP,
VK_DOWN, VK_DOWN,
VK_LEFT, VK_LEFT,
VK_RIGHT, VK_RIGHT,
VK_LSHIFT, VK_LSHIFT,
'I', 'I',
'K', 'K',
'J', 'J',
'L', 'L',
VK_LCONTROL, VK_LCONTROL,
'Q', 'Q',
'W', 'W',
0x00, 0x00,
0x00, 0x00,
}; };
#elif defined(HAVE_X11) && HAVE_X11 #elif defined(HAVE_X11) && HAVE_X11
{ {
XK_x, // A XK_x, // A
XK_z, // B XK_z, // B
XK_c, // X XK_c, // X
XK_s, // Y XK_s, // Y
XK_d, // Z XK_d, // Z
XK_Return, // Start XK_Return, // Start
XK_t, // D-pad up XK_t, // D-pad up
XK_g, // D-pad down XK_g, // D-pad down
XK_f, // D-pad left XK_f, // D-pad left
XK_h, // D-pad right XK_h, // D-pad right
XK_Up, // Main stick up XK_Up, // Main stick up
XK_Down, // Main stick down XK_Down, // Main stick down
XK_Left, // Main stick left XK_Left, // Main stick left
XK_Right, // Main stick right XK_Right, // Main stick right
XK_Shift_L, // Main stick semi XK_Shift_L, // Main stick semi
XK_i, // C-stick up XK_i, // C-stick up
XK_k, // C-stick down XK_k, // C-stick down
XK_j, // C-stick left XK_j, // C-stick left
XK_l, // C-stick right XK_l, // C-stick right
XK_Control_L, // C-stick semi XK_Control_L, // C-stick semi
XK_q, // L XK_q, // L
XK_w, // R XK_w, // R
0x00, // L semi-press 0x00, // L semi-press
0x00, // R semi-press 0x00, // R semi-press
}; };
#elif defined(HAVE_COCOA) && HAVE_COCOA #elif defined(HAVE_COCOA) && HAVE_COCOA
// Reference for Cocoa key codes: // Reference for Cocoa key codes:
// http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes // http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes
{ {
7, // A (x) 7, // A (x)
6, // B (z) 6, // B (z)
8, // X (c) 8, // X (c)
1, // Y (s) 1, // Y (s)
2, // Z (d) 2, // Z (d)
36, // Start (return) 36, // Start (return)
17, // D-pad up (t) 17, // D-pad up (t)
5, // D-pad down (g) 5, // D-pad down (g)
3, // D-pad left (f) 3, // D-pad left (f)
4, // D-pad right (h) 4, // D-pad right (h)
126, // Main stick up (up) 126, // Main stick up (up)
125, // Main stick down (down) 125, // Main stick down (down)
123, // Main stick left (left) 123, // Main stick left (left)
124, // Main stick right (right) 124, // Main stick right (right)
56, // Main stick semi (left shift) 56, // Main stick semi (left shift)
34, // C-stick up (i) 34, // C-stick up (i)
40, // C-stick down (k) 40, // C-stick down (k)
38, // C-stick left (j) 38, // C-stick left (j)
37, // C-stick right (l) 37, // C-stick right (l)
59, // C-stick semi (left control) 59, // C-stick semi (left control)
12, // L (q) 12, // L (q)
13, // R (w) 13, // R (w)
-1, // L semi-press (none) -1, // L semi-press (none)
-1, // R semi-press (none) -1, // R semi-press (none)
}; };
#endif #endif
Config g_Config; Config g_Config;
// Run when created // Run when created
// ----------------- // -----------------
Config::Config() Config::Config()
{ {
} }
// Save settings to file // Save settings to file
// --------------------- // ---------------------
void Config::Save() void Config::Save()
{ {
// Load ini file // Load ini file
IniFile file; IniFile file;
file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "GCPad.ini").c_str()); file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "GCPad.ini").c_str());
// ================================================================== // ==================================================================
// Global settings // Global settings
file.Set("General", "NoTriggerFilter", g_Config.bNoTriggerFilter); file.Set("General", "NoTriggerFilter", g_Config.bNoTriggerFilter);
#ifdef RERECORDING #ifdef RERECORDING
file.Set("General", "Recording", g_Config.bRecording); file.Set("General", "Recording", g_Config.bRecording);
file.Set("General", "Playback", g_Config.bPlayback); file.Set("General", "Playback", g_Config.bPlayback);
#endif #endif
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
// ================================================================== // ==================================================================
// Slot specific settings only // Slot specific settings only
std::string SectionName = StringFromFormat("GCPad%i", i+1); std::string SectionName = StringFromFormat("GCPad%i", i+1);
file.Set(SectionName.c_str(), "DeviceID", GCMapping[i].ID); file.Set(SectionName.c_str(), "DeviceID", GCMapping[i].ID);
file.Set(SectionName.c_str(), "Axis_Lx", GCMapping[i].AxisMapping.Lx); file.Set(SectionName.c_str(), "Axis_Lx", GCMapping[i].AxisMapping.Lx);
file.Set(SectionName.c_str(), "Axis_Ly", GCMapping[i].AxisMapping.Ly); file.Set(SectionName.c_str(), "Axis_Ly", GCMapping[i].AxisMapping.Ly);
file.Set(SectionName.c_str(), "Axis_Rx", GCMapping[i].AxisMapping.Rx); file.Set(SectionName.c_str(), "Axis_Rx", GCMapping[i].AxisMapping.Rx);
file.Set(SectionName.c_str(), "Axis_Ry", GCMapping[i].AxisMapping.Ry); file.Set(SectionName.c_str(), "Axis_Ry", GCMapping[i].AxisMapping.Ry);
file.Set(SectionName.c_str(), "Trigger_L", GCMapping[i].AxisMapping.Tl); file.Set(SectionName.c_str(), "Trigger_L", GCMapping[i].AxisMapping.Tl);
file.Set(SectionName.c_str(), "Trigger_R", GCMapping[i].AxisMapping.Tr); file.Set(SectionName.c_str(), "Trigger_R", GCMapping[i].AxisMapping.Tr);
file.Set(SectionName.c_str(), "DeadZoneL", GCMapping[i].DeadZoneL); file.Set(SectionName.c_str(), "DeadZoneL", GCMapping[i].DeadZoneL);
file.Set(SectionName.c_str(), "DeadZoneR", GCMapping[i].DeadZoneR); file.Set(SectionName.c_str(), "DeadZoneR", GCMapping[i].DeadZoneR);
file.Set(SectionName.c_str(), "Diagonal", GCMapping[i].Diagonal); file.Set(SectionName.c_str(), "Diagonal", GCMapping[i].Diagonal);
file.Set(SectionName.c_str(), "Square2Circle", GCMapping[i].bSquare2Circle); file.Set(SectionName.c_str(), "Square2Circle", GCMapping[i].bSquare2Circle);
file.Set(SectionName.c_str(), "Rumble", GCMapping[i].Rumble); file.Set(SectionName.c_str(), "Rumble", GCMapping[i].Rumble);
file.Set(SectionName.c_str(), "RumbleStrength", GCMapping[i].RumbleStrength); file.Set(SectionName.c_str(), "RumbleStrength", GCMapping[i].RumbleStrength);
file.Set(SectionName.c_str(), "TriggerType", GCMapping[i].TriggerType); file.Set(SectionName.c_str(), "TriggerType", GCMapping[i].TriggerType);
file.Set(SectionName.c_str(), "Source_Stick", GCMapping[i].Stick.Main); file.Set(SectionName.c_str(), "Source_Stick", GCMapping[i].Stick.Main);
file.Set(SectionName.c_str(), "Source_CStick", GCMapping[i].Stick.Sub); file.Set(SectionName.c_str(), "Source_CStick", GCMapping[i].Stick.Sub);
file.Set(SectionName.c_str(), "Source_Shoulder", GCMapping[i].Stick.Shoulder); file.Set(SectionName.c_str(), "Source_Shoulder", GCMapping[i].Stick.Shoulder);
file.Set(SectionName.c_str(), "Pressure_Stick", GCMapping[i].Pressure.Main); file.Set(SectionName.c_str(), "Pressure_Stick", GCMapping[i].Pressure.Main);
file.Set(SectionName.c_str(), "Pressure_CStick", GCMapping[i].Pressure.Sub); file.Set(SectionName.c_str(), "Pressure_CStick", GCMapping[i].Pressure.Sub);
file.Set(SectionName.c_str(), "Pressure_Shoulder", GCMapping[i].Pressure.Shoulder); file.Set(SectionName.c_str(), "Pressure_Shoulder", GCMapping[i].Pressure.Shoulder);
// ButtonMapping // ButtonMapping
for (int x = 0; x < LAST_CONSTANT; x++) for (int x = 0; x < LAST_CONSTANT; x++)
file.Set(SectionName.c_str(), gcControlNames[x], GCMapping[i].Button[x]); file.Set(SectionName.c_str(), gcControlNames[x], GCMapping[i].Button[x]);
} }
file.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "GCPad.ini").c_str()); file.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "GCPad.ini").c_str());
} }
// Load settings from file // Load settings from file
// ----------------------- // -----------------------
void Config::Load() void Config::Load()
{ {
// Load file // Load file
IniFile file; IniFile file;
file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "GCPad.ini").c_str()); file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "GCPad.ini").c_str());
// ================================================================== // ==================================================================
// Global settings // Global settings
file.Get("General", "NoTriggerFilter", &g_Config.bNoTriggerFilter, false); file.Get("General", "NoTriggerFilter", &g_Config.bNoTriggerFilter, false);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
std::string SectionName = StringFromFormat("GCPad%i", i+1); std::string SectionName = StringFromFormat("GCPad%i", i+1);
file.Get(SectionName.c_str(), "DeviceID", &GCMapping[i].ID, 0); file.Get(SectionName.c_str(), "DeviceID", &GCMapping[i].ID, 0);
file.Get(SectionName.c_str(), "Axis_Lx", &GCMapping[i].AxisMapping.Lx, 0); file.Get(SectionName.c_str(), "Axis_Lx", &GCMapping[i].AxisMapping.Lx, 0);
file.Get(SectionName.c_str(), "Axis_Ly", &GCMapping[i].AxisMapping.Ly, 1); file.Get(SectionName.c_str(), "Axis_Ly", &GCMapping[i].AxisMapping.Ly, 1);
file.Get(SectionName.c_str(), "Axis_Rx", &GCMapping[i].AxisMapping.Rx, 2); file.Get(SectionName.c_str(), "Axis_Rx", &GCMapping[i].AxisMapping.Rx, 2);
file.Get(SectionName.c_str(), "Axis_Ry", &GCMapping[i].AxisMapping.Ry, 3); file.Get(SectionName.c_str(), "Axis_Ry", &GCMapping[i].AxisMapping.Ry, 3);
file.Get(SectionName.c_str(), "Trigger_L", &GCMapping[i].AxisMapping.Tl, 1004); file.Get(SectionName.c_str(), "Trigger_L", &GCMapping[i].AxisMapping.Tl, 1004);
file.Get(SectionName.c_str(), "Trigger_R", &GCMapping[i].AxisMapping.Tr, 1005); file.Get(SectionName.c_str(), "Trigger_R", &GCMapping[i].AxisMapping.Tr, 1005);
file.Get(SectionName.c_str(), "DeadZoneL", &GCMapping[i].DeadZoneL, 0); file.Get(SectionName.c_str(), "DeadZoneL", &GCMapping[i].DeadZoneL, 0);
file.Get(SectionName.c_str(), "DeadZoneR", &GCMapping[i].DeadZoneR, 0); file.Get(SectionName.c_str(), "DeadZoneR", &GCMapping[i].DeadZoneR, 0);
file.Get(SectionName.c_str(), "Diagonal", &GCMapping[i].Diagonal, 100); file.Get(SectionName.c_str(), "Diagonal", &GCMapping[i].Diagonal, 100);
file.Get(SectionName.c_str(), "Square2Circle", &GCMapping[i].bSquare2Circle, false); file.Get(SectionName.c_str(), "Square2Circle", &GCMapping[i].bSquare2Circle, false);
file.Get(SectionName.c_str(), "Rumble", &GCMapping[i].Rumble, false); file.Get(SectionName.c_str(), "Rumble", &GCMapping[i].Rumble, false);
file.Get(SectionName.c_str(), "RumbleStrength", &GCMapping[i].RumbleStrength, 80); file.Get(SectionName.c_str(), "RumbleStrength", &GCMapping[i].RumbleStrength, 80);
file.Get(SectionName.c_str(), "TriggerType", &GCMapping[i].TriggerType, 0); file.Get(SectionName.c_str(), "TriggerType", &GCMapping[i].TriggerType, 0);
file.Get(SectionName.c_str(), "Source_Stick", &GCMapping[i].Stick.Main, 0); file.Get(SectionName.c_str(), "Source_Stick", &GCMapping[i].Stick.Main, 0);
file.Get(SectionName.c_str(), "Source_CStick", &GCMapping[i].Stick.Sub, 0); file.Get(SectionName.c_str(), "Source_CStick", &GCMapping[i].Stick.Sub, 0);
file.Get(SectionName.c_str(), "Source_Shoulder", &GCMapping[i].Stick.Shoulder, 0); file.Get(SectionName.c_str(), "Source_Shoulder", &GCMapping[i].Stick.Shoulder, 0);
file.Get(SectionName.c_str(), "Pressure_Stick", &GCMapping[i].Pressure.Main, DEF_STICK_HALF); file.Get(SectionName.c_str(), "Pressure_Stick", &GCMapping[i].Pressure.Main, DEF_STICK_HALF);
file.Get(SectionName.c_str(), "Pressure_CStick", &GCMapping[i].Pressure.Sub, DEF_STICK_HALF); file.Get(SectionName.c_str(), "Pressure_CStick", &GCMapping[i].Pressure.Sub, DEF_STICK_HALF);
file.Get(SectionName.c_str(), "Pressure_Shoulder", &GCMapping[i].Pressure.Shoulder, DEF_TRIGGER_HALF); file.Get(SectionName.c_str(), "Pressure_Shoulder", &GCMapping[i].Pressure.Shoulder, DEF_TRIGGER_HALF);
// ButtonMapping // ButtonMapping
for (int x = 0; x < LAST_CONSTANT; x++) for (int x = 0; x < LAST_CONSTANT; x++)
file.Get(SectionName.c_str(), gcControlNames[x], &GCMapping[i].Button[x], gcDefaultControls[x]); file.Get(SectionName.c_str(), gcControlNames[x], &GCMapping[i].Button[x], gcDefaultControls[x]);
} }
} }

View File

@ -1,49 +1,49 @@
// Project description // Project description
// ------------------- // -------------------
// Name: nJoy // Name: nJoy
// Description: A Dolphin Compatible Input Plugin // Description: A Dolphin Compatible Input Plugin
// //
// Author: Falcon4ever (nJoy@falcon4ever.com) // Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net // Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// //
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _PLUGIN_GCPAD_CONFIG_H #ifndef _PLUGIN_GCPAD_CONFIG_H
#define _PLUGIN_GCPAD_CONFIG_H #define _PLUGIN_GCPAD_CONFIG_H
struct Config struct Config
{ {
Config(); Config();
void Load(); void Load();
void Save(); void Save();
// General // General
bool bNoTriggerFilter; bool bNoTriggerFilter;
#ifdef RERECORDING #ifdef RERECORDING
bool bRecording; bool bRecording;
bool bPlayback; bool bPlayback;
#endif #endif
}; };
extern Config g_Config; extern Config g_Config;
#endif // _PLUGIN_GCPAD_CONFIG_H #endif // _PLUGIN_GCPAD_CONFIG_H

File diff suppressed because it is too large Load Diff

View File

@ -1,321 +1,321 @@
// Project description // Project description
// ------------------- // -------------------
// Name: nJoy // Name: nJoy
// Description: A Dolphin Compatible Input Plugin // Description: A Dolphin Compatible Input Plugin
// //
// Author: Falcon4ever (nJoy@falcon4ever.com) // Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net // Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// //
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Config.h" #include "Config.h"
#include "ConfigBox.h" #include "ConfigBox.h"
#include "GCPad.h" #include "GCPad.h"
// Replace the harder to understand -1 with "" for the sake of user friendliness // Replace the harder to understand -1 with "" for the sake of user friendliness
void GCPadConfigDialog::ToBlank(bool ToBlank, int Id) void GCPadConfigDialog::ToBlank(bool ToBlank, int Id)
{ {
if (!m_ControlsCreated) if (!m_ControlsCreated)
return; return;
if(ToBlank) if(ToBlank)
{ {
if (GetButtonText(Id) == wxString(wxT("-1"))) if (GetButtonText(Id) == wxString(wxT("-1")))
SetButtonText(Id, wxString()); SetButtonText(Id, wxString());
} }
else else
{ {
if (GetButtonText(Id).IsEmpty()) if (GetButtonText(Id).IsEmpty())
SetButtonText(Id, wxString(wxT("-1"))); SetButtonText(Id, wxString(wxT("-1")));
} }
} }
void GCPadConfigDialog::DoChangeDeadZone() void GCPadConfigDialog::DoChangeDeadZone()
{ {
float Rad; float Rad;
Rad = (float)GCMapping[m_Page].DeadZoneL * ((float)BoxW / 100.0) * 0.5; Rad = (float)GCMapping[m_Page].DeadZoneL * ((float)BoxW / 100.0) * 0.5;
m_bmpDeadZoneLeftIn[m_Page]->SetBitmap(CreateBitmapClear()); m_bmpDeadZoneLeftIn[m_Page]->SetBitmap(CreateBitmapClear());
m_bmpDeadZoneLeftIn[m_Page]->SetSize(0, 0); m_bmpDeadZoneLeftIn[m_Page]->SetSize(0, 0);
m_bmpDeadZoneLeftIn[m_Page]->SetBitmap(CreateBitmapDeadZone((int)Rad)); m_bmpDeadZoneLeftIn[m_Page]->SetBitmap(CreateBitmapDeadZone((int)Rad));
m_bmpDeadZoneLeftIn[m_Page]->SetPosition(wxPoint(BoxW / 2 - (int)Rad, BoxH / 2 - (int)Rad)); m_bmpDeadZoneLeftIn[m_Page]->SetPosition(wxPoint(BoxW / 2 - (int)Rad, BoxH / 2 - (int)Rad));
m_bmpDeadZoneLeftIn[m_Page]->Refresh(); m_bmpDeadZoneLeftIn[m_Page]->Refresh();
Rad = (float)GCMapping[m_Page].DeadZoneR * ((float)BoxW / 100.0) * 0.5; Rad = (float)GCMapping[m_Page].DeadZoneR * ((float)BoxW / 100.0) * 0.5;
m_bmpDeadZoneRightIn[m_Page]->SetBitmap(CreateBitmapClear()); m_bmpDeadZoneRightIn[m_Page]->SetBitmap(CreateBitmapClear());
m_bmpDeadZoneRightIn[m_Page]->SetSize(0, 0); m_bmpDeadZoneRightIn[m_Page]->SetSize(0, 0);
m_bmpDeadZoneRightIn[m_Page]->SetBitmap(CreateBitmapDeadZone((int)Rad)); m_bmpDeadZoneRightIn[m_Page]->SetBitmap(CreateBitmapDeadZone((int)Rad));
m_bmpDeadZoneRightIn[m_Page]->SetPosition(wxPoint(BoxW / 2 - (int)Rad, BoxH / 2 - (int)Rad)); m_bmpDeadZoneRightIn[m_Page]->SetPosition(wxPoint(BoxW / 2 - (int)Rad, BoxH / 2 - (int)Rad));
m_bmpDeadZoneRightIn[m_Page]->Refresh(); m_bmpDeadZoneRightIn[m_Page]->Refresh();
} }
// Update the textbox for the buttons // Update the textbox for the buttons
void GCPadConfigDialog::SetButtonText(int id, const wxString &str) void GCPadConfigDialog::SetButtonText(int id, const wxString &str)
{ {
if (IDB_ANALOG_LEFT_X <= id && id <= IDB_TRIGGER_R) if (IDB_ANALOG_LEFT_X <= id && id <= IDB_TRIGGER_R)
m_Button_Analog[id - IDB_ANALOG_LEFT_X][m_Page]->SetLabel(str); m_Button_Analog[id - IDB_ANALOG_LEFT_X][m_Page]->SetLabel(str);
else if (IDB_BTN_A <= id && id <= IDB_SHDR_SEMI_R) else if (IDB_BTN_A <= id && id <= IDB_SHDR_SEMI_R)
m_Button_GC[id - IDB_BTN_A][m_Page]->SetLabel(str); m_Button_GC[id - IDB_BTN_A][m_Page]->SetLabel(str);
} }
// Get the text in the textbox for the buttons // Get the text in the textbox for the buttons
wxString GCPadConfigDialog::GetButtonText(int id) wxString GCPadConfigDialog::GetButtonText(int id)
{ {
if (IDB_ANALOG_LEFT_X <= id && id <= IDB_TRIGGER_R) if (IDB_ANALOG_LEFT_X <= id && id <= IDB_TRIGGER_R)
return m_Button_Analog[id - IDB_ANALOG_LEFT_X][m_Page]->GetLabel(); return m_Button_Analog[id - IDB_ANALOG_LEFT_X][m_Page]->GetLabel();
else if (IDB_BTN_A <= id && id <= IDB_SHDR_SEMI_R) else if (IDB_BTN_A <= id && id <= IDB_SHDR_SEMI_R)
return m_Button_GC[id - IDB_BTN_A][m_Page]->GetLabel(); return m_Button_GC[id - IDB_BTN_A][m_Page]->GetLabel();
return wxString(); return wxString();
} }
void GCPadConfigDialog::DoGetButtons(int _GetId) void GCPadConfigDialog::DoGetButtons(int _GetId)
{ {
// Collect the starting values // Collect the starting values
// Get the current controller // Get the current controller
int PadID = GCMapping[m_Page].ID; int PadID = GCMapping[m_Page].ID;
// Get the controller and trigger type // Get the controller and trigger type
int TriggerType = GCMapping[m_Page].TriggerType; int TriggerType = GCMapping[m_Page].TriggerType;
// Collect the accepted buttons for this slot // Collect the accepted buttons for this slot
bool LeftRight = (_GetId == IDB_TRIGGER_L || _GetId == IDB_TRIGGER_R); bool LeftRight = (_GetId == IDB_TRIGGER_L || _GetId == IDB_TRIGGER_R);
bool Axis = (_GetId >= IDB_ANALOG_LEFT_X && _GetId <= IDB_TRIGGER_R) bool Axis = (_GetId >= IDB_ANALOG_LEFT_X && _GetId <= IDB_TRIGGER_R)
// Don't allow SDL axis input for the shoulder buttons if XInput is selected // Don't allow SDL axis input for the shoulder buttons if XInput is selected
&& !(TriggerType == InputCommon::CTL_TRIGGER_XINPUT && (_GetId == IDB_TRIGGER_L || _GetId == IDB_TRIGGER_R) ); && !(TriggerType == InputCommon::CTL_TRIGGER_XINPUT && (_GetId == IDB_TRIGGER_L || _GetId == IDB_TRIGGER_R) );
bool XInput = (TriggerType == InputCommon::CTL_TRIGGER_XINPUT); bool XInput = (TriggerType == InputCommon::CTL_TRIGGER_XINPUT);
bool Button = (_GetId >= IDB_BTN_A && _GetId <= IDB_SHDR_SEMI_R); bool Button = (_GetId >= IDB_BTN_A && _GetId <= IDB_SHDR_SEMI_R);
bool Hat = (_GetId >= IDB_BTN_A && _GetId <= IDB_SHDR_SEMI_R); bool Hat = (_GetId >= IDB_BTN_A && _GetId <= IDB_SHDR_SEMI_R);
bool NoTriggerFilter = g_Config.bNoTriggerFilter; bool NoTriggerFilter = g_Config.bNoTriggerFilter;
// Values used in this function // Values used in this function
int Seconds = 4; // Seconds to wait for int Seconds = 4; // Seconds to wait for
int TimesPerSecond = 40; // How often to run the check int TimesPerSecond = 40; // How often to run the check
// Values returned from InputCommon::GetButton() // Values returned from InputCommon::GetButton()
int value; // Axis value or Hat value int value; // Axis value or Hat value
int type; // Button type int type; // Button type
int KeyPressed = 0; int KeyPressed = 0;
int pressed = 0; int pressed = 0;
bool Succeed = false; bool Succeed = false;
bool Stop = false; // Stop the timer bool Stop = false; // Stop the timer
// If the Id has changed or the timer is not running we should start one // If the Id has changed or the timer is not running we should start one
if( GetButtonWaitingID != _GetId || !m_ButtonMappingTimer->IsRunning() ) if( GetButtonWaitingID != _GetId || !m_ButtonMappingTimer->IsRunning() )
{ {
if(m_ButtonMappingTimer->IsRunning()) if(m_ButtonMappingTimer->IsRunning())
m_ButtonMappingTimer->Stop(); m_ButtonMappingTimer->Stop();
// Save the button Id // Save the button Id
GetButtonWaitingID = _GetId; GetButtonWaitingID = _GetId;
GetButtonWaitingTimer = 0; GetButtonWaitingTimer = 0;
// Start the timer // Start the timer
#if wxUSE_TIMER #if wxUSE_TIMER
m_ButtonMappingTimer->Start(1000 / TimesPerSecond); m_ButtonMappingTimer->Start(1000 / TimesPerSecond);
#endif #endif
DEBUG_LOG(PAD, "Timer Started: Pad:%i _GetId:%i " DEBUG_LOG(PAD, "Timer Started: Pad:%i _GetId:%i "
"Allowed input is Axis:%i LeftRight:%i XInput:%i Button:%i Hat:%i", "Allowed input is Axis:%i LeftRight:%i XInput:%i Button:%i Hat:%i",
GCMapping[m_Page].ID, _GetId, GCMapping[m_Page].ID, _GetId,
Axis, LeftRight, XInput, Button, Hat); Axis, LeftRight, XInput, Button, Hat);
} }
// Check for buttons // Check for buttons
// If there is a timer we should not create a new one // If there is a timer we should not create a new one
else if (NumGoodPads > 0) else if (NumGoodPads > 0)
{ {
InputCommon::GetButton( InputCommon::GetButton(
GCMapping[m_Page].joy, PadID, joyinfo[PadID].NumButtons, joyinfo[PadID].NumAxes, joyinfo[PadID].NumHats, GCMapping[m_Page].joy, PadID, joyinfo[PadID].NumButtons, joyinfo[PadID].NumAxes, joyinfo[PadID].NumHats,
KeyPressed, value, type, pressed, Succeed, Stop, KeyPressed, value, type, pressed, Succeed, Stop,
LeftRight, Axis, XInput, Button, Hat, NoTriggerFilter); LeftRight, Axis, XInput, Button, Hat, NoTriggerFilter);
} }
// Process results // Process results
// Count each time // Count each time
GetButtonWaitingTimer++; GetButtonWaitingTimer++;
// This is run every second // This is run every second
if (GetButtonWaitingTimer % TimesPerSecond == 0) if (GetButtonWaitingTimer % TimesPerSecond == 0)
{ {
// Current time // Current time
int TmpTime = Seconds - (GetButtonWaitingTimer / TimesPerSecond); int TmpTime = Seconds - (GetButtonWaitingTimer / TimesPerSecond);
// Update text // Update text
SetButtonText(_GetId, wxString::Format(wxT("[ %d ]"), TmpTime)); SetButtonText(_GetId, wxString::Format(wxT("[ %d ]"), TmpTime));
} }
// Time's up // Time's up
if (GetButtonWaitingTimer / TimesPerSecond >= Seconds) if (GetButtonWaitingTimer / TimesPerSecond >= Seconds)
{ {
Stop = true; Stop = true;
// Revert back to old label // Revert back to old label
SetButtonText(_GetId, OldLabel); SetButtonText(_GetId, OldLabel);
} }
// If we got a button // If we got a button
if(Succeed) if(Succeed)
{ {
Stop = true; Stop = true;
// We need to assign hat special code // We need to assign hat special code
if (type == InputCommon::CTL_HAT) if (type == InputCommon::CTL_HAT)
{ {
// Index of pressed starts from 0 // Index of pressed starts from 0
if (value & SDL_HAT_UP) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_UP; if (value & SDL_HAT_UP) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_UP;
else if (value & SDL_HAT_DOWN) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_DOWN; else if (value & SDL_HAT_DOWN) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_DOWN;
else if (value & SDL_HAT_LEFT) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_LEFT; else if (value & SDL_HAT_LEFT) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_LEFT;
else if (value & SDL_HAT_RIGHT) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_RIGHT; else if (value & SDL_HAT_RIGHT) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_RIGHT;
else pressed = -1; else pressed = -1;
} }
if (IDB_BTN_A <= _GetId && _GetId <= IDB_SHDR_SEMI_R) if (IDB_BTN_A <= _GetId && _GetId <= IDB_SHDR_SEMI_R)
{ {
// Better make the pad button code far from virtual key code // Better make the pad button code far from virtual key code
SaveButtonMapping(_GetId, 0x1000 + pressed); SaveButtonMapping(_GetId, 0x1000 + pressed);
SetButtonText(_GetId, wxString::Format(wxT("PAD: %d"), pressed)); SetButtonText(_GetId, wxString::Format(wxT("PAD: %d"), pressed));
} }
else if (IDB_ANALOG_LEFT_X <= _GetId && _GetId <= IDB_TRIGGER_R) else if (IDB_ANALOG_LEFT_X <= _GetId && _GetId <= IDB_TRIGGER_R)
{ {
SaveButtonMapping(_GetId, pressed); SaveButtonMapping(_GetId, pressed);
SetButtonText(_GetId, wxString::Format(wxT("%d"), pressed)); SetButtonText(_GetId, wxString::Format(wxT("%d"), pressed));
} }
} }
// Stop the timer // Stop the timer
if(Stop) if(Stop)
{ {
DEBUG_LOG(PAD, "Timer Stopped for Pad:%i _GetId:%i", GCMapping[m_Page].ID, _GetId); DEBUG_LOG(PAD, "Timer Stopped for Pad:%i _GetId:%i", GCMapping[m_Page].ID, _GetId);
m_ButtonMappingTimer->Stop(); m_ButtonMappingTimer->Stop();
GetButtonWaitingTimer = 0; GetButtonWaitingTimer = 0;
GetButtonWaitingID = 0; GetButtonWaitingID = 0;
ClickedButton = NULL; ClickedButton = NULL;
} }
// If we got a bad button // If we got a bad button
if(KeyPressed == -1) if(KeyPressed == -1)
{ {
// Update text // Update text
SetButtonText(_GetId, wxString(wxT("PAD: -1"))); SetButtonText(_GetId, wxString(wxT("PAD: -1")));
// Notify the user // Notify the user
wxMessageBox(wxString::Format( wxMessageBox(wxString::Format(
wxT("You selected a key with a to low key code (%i), please") wxT("You selected a key with a to low key code (%i), please")
wxT(" select another key with a higher key code."), pressed) wxT(" select another key with a higher key code."), pressed)
, wxT("Notice"), wxICON_INFORMATION); , wxT("Notice"), wxICON_INFORMATION);
} }
} }
// Convert the 0x8000 range values to BoxW and BoxH for the plot // Convert the 0x8000 range values to BoxW and BoxH for the plot
void GCPadConfigDialog::Convert2Box(int &x) void GCPadConfigDialog::Convert2Box(int &x)
{ {
// Border adjustment // Border adjustment
int BoxW_ = BoxW - 2; int BoxH_ = BoxH - 2; int BoxW_ = BoxW - 2; int BoxH_ = BoxH - 2;
// Convert values // Convert values
x = (BoxW_ / 2) + (x * BoxW_ / (32767 * 2)); x = (BoxW_ / 2) + (x * BoxW_ / (32767 * 2));
} }
// Update the input status boxes // Update the input status boxes
void GCPadConfigDialog::UpdatePadInfo(wxTimerEvent& WXUNUSED(event)) void GCPadConfigDialog::UpdatePadInfo(wxTimerEvent& WXUNUSED(event))
{ {
if (GCMapping[m_Page].ID < 0 || GCMapping[m_Page].ID >= NumPads) if (GCMapping[m_Page].ID < 0 || GCMapping[m_Page].ID >= NumPads)
{ {
m_tStatusLeftIn[m_Page]->SetLabel(wxT("Not connected")); m_tStatusLeftIn[m_Page]->SetLabel(wxT("Not connected"));
m_tStatusLeftOut[m_Page]->SetLabel(wxT("Not connected")); m_tStatusLeftOut[m_Page]->SetLabel(wxT("Not connected"));
m_tStatusRightIn[m_Page]->SetLabel(wxT("Not connected")); m_tStatusRightIn[m_Page]->SetLabel(wxT("Not connected"));
m_tStatusRightOut[m_Page]->SetLabel(wxT("Not connected")); m_tStatusRightOut[m_Page]->SetLabel(wxT("Not connected"));
m_TriggerStatusL[m_Page]->SetLabel(wxT("000")); m_TriggerStatusL[m_Page]->SetLabel(wxT("000"));
m_TriggerStatusR[m_Page]->SetLabel(wxT("000")); m_TriggerStatusR[m_Page]->SetLabel(wxT("000"));
return; return;
} }
// Check that Dolphin is in focus, otherwise don't update the pad status // Check that Dolphin is in focus, otherwise don't update the pad status
//if (IsFocus()) //if (IsFocus())
GetAxisState(GCMapping[m_Page]); GetAxisState(GCMapping[m_Page]);
// Analog stick // Analog stick
// Get original values // Get original values
int main_x = GCMapping[m_Page].AxisState.Lx; int main_x = GCMapping[m_Page].AxisState.Lx;
int main_y = GCMapping[m_Page].AxisState.Ly; int main_y = GCMapping[m_Page].AxisState.Ly;
int right_x = GCMapping[m_Page].AxisState.Rx; int right_x = GCMapping[m_Page].AxisState.Rx;
int right_y = GCMapping[m_Page].AxisState.Ry; int right_y = GCMapping[m_Page].AxisState.Ry;
// Get adjusted values // Get adjusted values
int main_x_after = main_x, main_y_after = main_y; int main_x_after = main_x, main_y_after = main_y;
int right_x_after = right_x, right_y_after = right_y; int right_x_after = right_x, right_y_after = right_y;
// Produce square // Produce square
if(GCMapping[m_Page].bSquare2Circle) if(GCMapping[m_Page].bSquare2Circle)
InputCommon::Square2Circle(main_x_after, main_y_after, GCMapping[m_Page].Diagonal, false); InputCommon::Square2Circle(main_x_after, main_y_after, GCMapping[m_Page].Diagonal, false);
// Check dead zone // Check dead zone
float DeadZoneLeft = (float)GCMapping[m_Page].DeadZoneL / 100.0; float DeadZoneLeft = (float)GCMapping[m_Page].DeadZoneL / 100.0;
float DeadZoneRight = (float)GCMapping[m_Page].DeadZoneR / 100.0; float DeadZoneRight = (float)GCMapping[m_Page].DeadZoneR / 100.0;
if (InputCommon::IsDeadZone(DeadZoneLeft, main_x_after, main_y_after)) if (InputCommon::IsDeadZone(DeadZoneLeft, main_x_after, main_y_after))
{ {
main_x_after = 0; main_x_after = 0;
main_y_after = 0; main_y_after = 0;
} }
if (InputCommon::IsDeadZone(DeadZoneRight, right_x_after, right_y_after)) if (InputCommon::IsDeadZone(DeadZoneRight, right_x_after, right_y_after))
{ {
right_x_after = 0; right_x_after = 0;
right_y_after = 0; right_y_after = 0;
} }
int Lx = InputCommon::Pad_Convert(main_x); int Ly = InputCommon::Pad_Convert(main_y); int Lx = InputCommon::Pad_Convert(main_x); int Ly = InputCommon::Pad_Convert(main_y);
int Rx = InputCommon::Pad_Convert(right_x); int Ry = InputCommon::Pad_Convert(right_y); int Rx = InputCommon::Pad_Convert(right_x); int Ry = InputCommon::Pad_Convert(right_y);
int Lx_after = InputCommon::Pad_Convert(main_x_after); int Ly_after = InputCommon::Pad_Convert(main_y_after); int Lx_after = InputCommon::Pad_Convert(main_x_after); int Ly_after = InputCommon::Pad_Convert(main_y_after);
int Rx_after = InputCommon::Pad_Convert(right_x_after); int Ry_after = InputCommon::Pad_Convert(right_y_after); int Rx_after = InputCommon::Pad_Convert(right_x_after); int Ry_after = InputCommon::Pad_Convert(right_y_after);
m_tStatusLeftIn[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Lx, Ly)); m_tStatusLeftIn[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Lx, Ly));
m_tStatusLeftOut[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Lx_after, Ly_after)); m_tStatusLeftOut[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Lx_after, Ly_after));
m_tStatusRightIn[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Rx, Ry)); m_tStatusRightIn[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Rx, Ry));
m_tStatusRightOut[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Rx_after, Ry_after)); m_tStatusRightOut[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Rx_after, Ry_after));
// Adjust the values for the plot // Adjust the values for the plot
Convert2Box(main_x); Convert2Box(main_y); Convert2Box(main_x); Convert2Box(main_y);
Convert2Box(right_x); Convert2Box(right_y); Convert2Box(right_x); Convert2Box(right_y);
Convert2Box(main_x_after); Convert2Box(main_y_after); Convert2Box(main_x_after); Convert2Box(main_y_after);
Convert2Box(right_x_after); Convert2Box(right_y_after); Convert2Box(right_x_after); Convert2Box(right_y_after);
// Adjust the dot // Adjust the dot
m_bmpDotLeftIn[m_Page]->SetPosition(wxPoint(main_x, main_y)); m_bmpDotLeftIn[m_Page]->SetPosition(wxPoint(main_x, main_y));
m_bmpDotLeftOut[m_Page]->SetPosition(wxPoint(main_x_after, main_y_after)); m_bmpDotLeftOut[m_Page]->SetPosition(wxPoint(main_x_after, main_y_after));
m_bmpDotRightIn[m_Page]->SetPosition(wxPoint(right_x, right_y)); m_bmpDotRightIn[m_Page]->SetPosition(wxPoint(right_x, right_y));
m_bmpDotRightOut[m_Page]->SetPosition(wxPoint(right_x_after, right_y_after)); m_bmpDotRightOut[m_Page]->SetPosition(wxPoint(right_x_after, right_y_after));
// Get the trigger values // Get the trigger values
int TriggerLeft = GCMapping[m_Page].AxisState.Tl; int TriggerLeft = GCMapping[m_Page].AxisState.Tl;
int TriggerRight = GCMapping[m_Page].AxisState.Tr; int TriggerRight = GCMapping[m_Page].AxisState.Tr;
// Convert the triggers values // Convert the triggers values
if (GCMapping[m_Page].TriggerType == InputCommon::CTL_TRIGGER_SDL) if (GCMapping[m_Page].TriggerType == InputCommon::CTL_TRIGGER_SDL)
{ {
TriggerLeft = InputCommon::Pad_Convert(TriggerLeft); TriggerLeft = InputCommon::Pad_Convert(TriggerLeft);
TriggerRight = InputCommon::Pad_Convert(TriggerRight); TriggerRight = InputCommon::Pad_Convert(TriggerRight);
} }
m_TriggerStatusL[m_Page]->SetLabel(wxString::Format(wxT("%03i"), TriggerLeft)); m_TriggerStatusL[m_Page]->SetLabel(wxString::Format(wxT("%03i"), TriggerLeft));
m_TriggerStatusR[m_Page]->SetLabel(wxString::Format(wxT("%03i"), TriggerRight)); m_TriggerStatusR[m_Page]->SetLabel(wxString::Format(wxT("%03i"), TriggerRight));
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,168 +1,168 @@
// Project description // Project description
// ------------------- // -------------------
// Name: nJoy // Name: nJoy
// Description: A Dolphin Compatible Input Plugin // Description: A Dolphin Compatible Input Plugin
// //
// Author: Falcon4ever (nJoy@falcon4ever.com) // Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net // Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// //
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _PLUGIN_GCPAD_H #ifndef _PLUGIN_GCPAD_H
#define _PLUGIN_GCPAD_H #define _PLUGIN_GCPAD_H
#include <vector> // System #include <vector> // System
#include <cstdio> #include <cstdio>
#include "../../../Core/InputCommon/Src/InputCommon.h" // Core #include "../../../Core/InputCommon/Src/InputCommon.h" // Core
#include "../../../Core/InputCommon/Src/SDL_Util.h" #include "../../../Core/InputCommon/Src/SDL_Util.h"
#ifdef _WIN32 #ifdef _WIN32
#include "../../../Core/InputCommon/Src/XInput_Util.h" #include "../../../Core/InputCommon/Src/XInput_Util.h"
#elif defined(HAVE_X11) && HAVE_X11 #elif defined(HAVE_X11) && HAVE_X11
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
//no need for Cocoa yet, but I guess ayuanx isn't done yet. //no need for Cocoa yet, but I guess ayuanx isn't done yet.
//#elif defined(HAVE_COCOA) && HAVE_COCOA //#elif defined(HAVE_COCOA) && HAVE_COCOA
// #include <Cocoa/Cocoa.h> // #include <Cocoa/Cocoa.h>
#endif #endif
#include "pluginspecs_pad.h" #include "pluginspecs_pad.h"
#define DEF_BUTTON_FULL 255 #define DEF_BUTTON_FULL 255
#define DEF_STICK_FULL 100 #define DEF_STICK_FULL 100
#define DEF_STICK_HALF 50 #define DEF_STICK_HALF 50
#define DEF_TRIGGER_FULL 255 #define DEF_TRIGGER_FULL 255
#define DEF_TRIGGER_HALF 128 #define DEF_TRIGGER_HALF 128
#define DEF_TRIGGER_THRESHOLD 230 #define DEF_TRIGGER_THRESHOLD 230
// GC Pad Buttons // GC Pad Buttons
enum EGCPad enum EGCPad
{ {
EGC_A = 0, EGC_A = 0,
EGC_B, EGC_B,
EGC_X, EGC_X,
EGC_Y, EGC_Y,
EGC_Z, EGC_Z,
EGC_START, EGC_START,
EGC_DPAD_UP, EGC_DPAD_UP,
EGC_DPAD_DOWN, EGC_DPAD_DOWN,
EGC_DPAD_LEFT, EGC_DPAD_LEFT,
EGC_DPAD_RIGHT, EGC_DPAD_RIGHT,
EGC_STICK_UP, EGC_STICK_UP,
EGC_STICK_DOWN, EGC_STICK_DOWN,
EGC_STICK_LEFT, EGC_STICK_LEFT,
EGC_STICK_RIGHT, EGC_STICK_RIGHT,
EGC_STICK_SEMI, EGC_STICK_SEMI,
EGC_CSTICK_UP, EGC_CSTICK_UP,
EGC_CSTICK_DOWN, EGC_CSTICK_DOWN,
EGC_CSTICK_LEFT, EGC_CSTICK_LEFT,
EGC_CSTICK_RIGHT, EGC_CSTICK_RIGHT,
EGC_CSTICK_SEMI, EGC_CSTICK_SEMI,
EGC_TGR_L, EGC_TGR_L,
EGC_TGR_R, EGC_TGR_R,
EGC_TGR_SEMI_L, EGC_TGR_SEMI_L,
EGC_TGR_SEMI_R, EGC_TGR_SEMI_R,
LAST_CONSTANT, LAST_CONSTANT,
}; };
enum EInputType enum EInputType
{ {
FROM_KEYBOARD, FROM_KEYBOARD,
FROM_ANALOG1, FROM_ANALOG1,
FROM_ANALOG2, FROM_ANALOG2,
FROM_TRIGGER, FROM_TRIGGER,
}; };
union UAxis union UAxis
{ {
int Code[6]; int Code[6];
struct struct
{ {
int Lx; int Lx;
int Ly; int Ly;
int Rx; int Rx;
int Ry; int Ry;
int Tl; // Trigger int Tl; // Trigger
int Tr; // Trigger int Tr; // Trigger
}; };
}; };
struct SStickMapping struct SStickMapping
{ {
int Main; int Main;
int Sub; int Sub;
int Shoulder; //Trigger int Shoulder; //Trigger
}; };
struct CONTROLLER_MAPPING_GC // PAD MAPPING GC struct CONTROLLER_MAPPING_GC // PAD MAPPING GC
{ {
int ID; // SDL joystick device ID int ID; // SDL joystick device ID
SDL_Joystick *joy; // SDL joystick device SDL_Joystick *joy; // SDL joystick device
UAxis AxisState; UAxis AxisState;
UAxis AxisMapping; // 6 Axes (Main, Sub, Triggers) UAxis AxisMapping; // 6 Axes (Main, Sub, Triggers)
int TriggerType; // SDL or XInput trigger int TriggerType; // SDL or XInput trigger
bool Rumble; bool Rumble;
int RumbleStrength; int RumbleStrength;
int DeadZoneL; // Analog 1 Deadzone int DeadZoneL; // Analog 1 Deadzone
int DeadZoneR; // Analog 2 Deadzone int DeadZoneR; // Analog 2 Deadzone
bool bSquare2Circle; bool bSquare2Circle;
int Diagonal; int Diagonal;
SStickMapping Stick; SStickMapping Stick;
SStickMapping Pressure; SStickMapping Pressure;
int Button[LAST_CONSTANT]; int Button[LAST_CONSTANT];
}; };
extern CONTROLLER_MAPPING_GC GCMapping[4]; extern CONTROLLER_MAPPING_GC GCMapping[4];
extern int NumPads, NumGoodPads, g_ID; extern int NumPads, NumGoodPads, g_ID;
extern SPADInitialize *g_PADInitialize; extern SPADInitialize *g_PADInitialize;
extern std::vector<InputCommon::CONTROLLER_INFO> joyinfo; extern std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
#ifdef _WIN32 #ifdef _WIN32
extern HWND m_hWnd; // Handle to window extern HWND m_hWnd; // Handle to window
#endif #endif
#if defined(HAVE_X11) && HAVE_X11 #if defined(HAVE_X11) && HAVE_X11
extern Display* WMdisplay; extern Display* WMdisplay;
#endif #endif
// Custom Functions // Custom Functions
// ---------------- // ----------------
void EmulateAnalogStick(unsigned char &stickX, unsigned char &stickY, bool buttonUp, bool buttonDown, bool buttonLeft, bool buttonRight, int magnitude); void EmulateAnalogStick(unsigned char &stickX, unsigned char &stickY, bool buttonUp, bool buttonDown, bool buttonLeft, bool buttonRight, int magnitude);
void EmulateAnalogTrigger(unsigned char &trL, unsigned char &trR); void EmulateAnalogTrigger(unsigned char &trL, unsigned char &trR);
void Close_Devices(); void Close_Devices();
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads); bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads);
void GetAxisState(CONTROLLER_MAPPING_GC &_GCMapping); void GetAxisState(CONTROLLER_MAPPING_GC &_GCMapping);
void UpdatePadState(CONTROLLER_MAPPING_GC &_GCMapping); void UpdatePadState(CONTROLLER_MAPPING_GC &_GCMapping);
bool IsKey(int Key); bool IsKey(int Key);
bool IsFocus(); bool IsFocus();
bool ReloadDLL(); bool ReloadDLL();
void PAD_RumbleClose(); void PAD_RumbleClose();
#endif // _PLUGIN_GCPAD_H #endif // _PLUGIN_GCPAD_H

View File

@ -1,181 +1,181 @@
// Project description // Project description
// ------------------- // -------------------
// Name: nJoy // Name: nJoy
// Description: A Dolphin Compatible Input Plugin // Description: A Dolphin Compatible Input Plugin
// //
// Author: Falcon4ever (nJoy@falcon4ever.com) // Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net // Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// //
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "GCPad.h" #include "GCPad.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "ChunkFile.h" #include "ChunkFile.h"
// TODO : // TODO :
// This is pretty much useless now with the TAS features right ? // This is pretty much useless now with the TAS features right ?
#ifdef RERECORDING #ifdef RERECORDING
namespace Recording namespace Recording
{ {
// Definitions // Definitions
// ------------- // -------------
// Pre defined maxium storage limit // Pre defined maxium storage limit
#define RECORD_SIZE (1024 * 128) #define RECORD_SIZE (1024 * 128)
SPADStatus RecordBuffer[RECORD_SIZE]; SPADStatus RecordBuffer[RECORD_SIZE];
int count = 0; int count = 0;
// Recording functions // Recording functions
// ------------- // -------------
void RecordInput(const SPADStatus& _rPADStatus) void RecordInput(const SPADStatus& _rPADStatus)
{ {
if (count >= RECORD_SIZE) return; if (count >= RECORD_SIZE) return;
RecordBuffer[count++] = _rPADStatus; RecordBuffer[count++] = _rPADStatus;
// Logging // Logging
//u8 TmpData[sizeof(SPADStatus)]; //u8 TmpData[sizeof(SPADStatus)];
//memcpy(TmpData, &RecordBuffer[count - 1], sizeof(SPADStatus)); //memcpy(TmpData, &RecordBuffer[count - 1], sizeof(SPADStatus));
//Console::Print("RecordInput(%i): %s\n", count, ArrayToString(TmpData, sizeof(SPADStatus), 0, 30).c_str()); //Console::Print("RecordInput(%i): %s\n", count, ArrayToString(TmpData, sizeof(SPADStatus), 0, 30).c_str());
// Auto save every ten seconds // Auto save every ten seconds
if (count % (60 * 10) == 0) Save(); if (count % (60 * 10) == 0) Save();
} }
const SPADStatus& Play() const SPADStatus& Play()
{ {
// Logging // Logging
//Console::Print("PlayRecord(%i)\n", count); //Console::Print("PlayRecord(%i)\n", count);
if (count >= RECORD_SIZE) if (count >= RECORD_SIZE)
{ {
// Todo: Make the recording size unlimited? // Todo: Make the recording size unlimited?
//PanicAlert("The recording reached its end"); //PanicAlert("The recording reached its end");
return(RecordBuffer[0]); return(RecordBuffer[0]);
} }
return(RecordBuffer[count++]); return(RecordBuffer[count++]);
} }
void Load() void Load()
{ {
FILE* pStream = fopen("pad-record.bin", "rb"); FILE* pStream = fopen("pad-record.bin", "rb");
if (pStream != NULL) if (pStream != NULL)
{ {
fread(RecordBuffer, 1, RECORD_SIZE * sizeof(SPADStatus), pStream); fread(RecordBuffer, 1, RECORD_SIZE * sizeof(SPADStatus), pStream);
fclose(pStream); fclose(pStream);
} }
else else
{ {
PanicAlert("SimplePad: Could not open pad-record.bin"); PanicAlert("SimplePad: Could not open pad-record.bin");
} }
//Console::Print("LoadRecord()"); //Console::Print("LoadRecord()");
} }
void Save() void Save()
{ {
// Open the file in a way that clears all old data // Open the file in a way that clears all old data
FILE* pStream = fopen("pad-record.bin", "wb"); FILE* pStream = fopen("pad-record.bin", "wb");
if (pStream != NULL) if (pStream != NULL)
{ {
fwrite(RecordBuffer, 1, RECORD_SIZE * sizeof(SPADStatus), pStream); fwrite(RecordBuffer, 1, RECORD_SIZE * sizeof(SPADStatus), pStream);
fclose(pStream); fclose(pStream);
} }
else else
{ {
PanicAlert("NJoy: Could not save pad-record.bin"); PanicAlert("NJoy: Could not save pad-record.bin");
} }
//PanicAlert("SaveRecord()"); //PanicAlert("SaveRecord()");
//Console::Print("SaveRecord()"); //Console::Print("SaveRecord()");
} }
void Initialize() void Initialize()
{ {
// ------------------------------------------- // -------------------------------------------
// Rerecording // Rerecording
// ---------------------- // ----------------------
#ifdef RERECORDING #ifdef RERECORDING
/* Check if we are starting the pad to record the input, and an old file exists. In that case ask /* Check if we are starting the pad to record the input, and an old file exists. In that case ask
if we really want to start the recording and eventually overwrite the file */ if we really want to start the recording and eventually overwrite the file */
if (g_Config.bRecording && File::Exists("pad-record.bin")) if (g_Config.bRecording && File::Exists("pad-record.bin"))
{ {
if (!AskYesNo("An old version of '%s' aleady exists in your Dolphin directory. You can" if (!AskYesNo("An old version of '%s' aleady exists in your Dolphin directory. You can"
" now make a copy of it before you start a new recording and overwrite the file." " now make a copy of it before you start a new recording and overwrite the file."
" Select Yes to continue and overwrite the file. Select No to turn off the input" " Select Yes to continue and overwrite the file. Select No to turn off the input"
" recording and continue without recording anything.", " recording and continue without recording anything.",
"pad-record.bin")) "pad-record.bin"))
{ {
// Turn off recording and continue // Turn off recording and continue
g_Config.bRecording = false; g_Config.bRecording = false;
} }
} }
// Load recorded input if we are to play it back, otherwise begin with a blank recording // Load recorded input if we are to play it back, otherwise begin with a blank recording
if (g_Config.bPlayback) Recording::Load(); if (g_Config.bPlayback) Recording::Load();
#endif #endif
// ---------------------- // ----------------------
} }
void ShutDown() void ShutDown()
{ {
// Save recording // Save recording
if (g_Config.bRecording) Recording::Save(); if (g_Config.bRecording) Recording::Save();
// Reset the counter // Reset the counter
count = 0; count = 0;
} }
void DoState(unsigned char **ptr, int mode) void DoState(unsigned char **ptr, int mode)
{ {
// Load or save the counter // Load or save the counter
PointerWrap p(ptr, mode); PointerWrap p(ptr, mode);
p.Do(count); p.Do(count);
//Console::Print("count: %i\n", count); //Console::Print("count: %i\n", count);
// Update the frame counter for the sake of the status bar // Update the frame counter for the sake of the status bar
if (mode == PointerWrap::MODE_READ) if (mode == PointerWrap::MODE_READ)
{ {
#ifdef _WIN32 #ifdef _WIN32
// This only works when rendering to the main window, I think // This only works when rendering to the main window, I think
PostMessage(GetParent(g_PADInitialize->hWnd), WM_USER, INPUT_FRAME_COUNTER, count); PostMessage(GetParent(g_PADInitialize->hWnd), WM_USER, INPUT_FRAME_COUNTER, count);
#endif #endif
} }
} }
} // Recording } // Recording
#endif // RERECORDING #endif // RERECORDING

View File

@ -1,409 +1,409 @@
// Project description // Project description
// ------------------- // -------------------
// Name: nJoy // Name: nJoy
// Description: A Dolphin Compatible Input Plugin // Description: A Dolphin Compatible Input Plugin
// //
// Author: Falcon4ever (nJoy@falcon4ever.com) // Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net // Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// //
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "GCPad.h" #include "GCPad.h"
#ifdef _WIN32 #ifdef _WIN32
#include "XInput.h" #include "XInput.h"
#endif #endif
// SDL Haptic fails on windows, it just doesn't work (even the sample doesn't work) // SDL Haptic fails on windows, it just doesn't work (even the sample doesn't work)
// So until i can make it work, this is all disabled >:( // So until i can make it work, this is all disabled >:(
#if SDL_VERSION_ATLEAST(1, 3, 0) && !defined(_WIN32) && !defined(__APPLE__) #if SDL_VERSION_ATLEAST(1, 3, 0) && !defined(_WIN32) && !defined(__APPLE__)
#define SDL_RUMBLE #define SDL_RUMBLE
#else #else
#ifdef _WIN32 #ifdef _WIN32
#define RUMBLE_HACK #define RUMBLE_HACK
#define DIRECTINPUT_VERSION 0x0800 #define DIRECTINPUT_VERSION 0x0800
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#pragma comment(lib, "dxguid.lib") #pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dinput8.lib") #pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "winmm.lib") #pragma comment(lib, "winmm.lib")
#include <dinput.h> #include <dinput.h>
#endif #endif
#endif #endif
#ifdef RUMBLE_HACK #ifdef RUMBLE_HACK
struct RUMBLE // GC Pad rumble DIDevice struct RUMBLE // GC Pad rumble DIDevice
{ {
LPDIRECTINPUTDEVICE8 g_pDevice; // 4 pads objects LPDIRECTINPUTDEVICE8 g_pDevice; // 4 pads objects
LPDIRECTINPUTEFFECT g_pEffect; LPDIRECTINPUTEFFECT g_pEffect;
DWORD g_dwNumForceFeedbackAxis; DWORD g_dwNumForceFeedbackAxis;
DIEFFECT eff; DIEFFECT eff;
}; };
BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext); BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext);
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext); BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext);
void SetDeviceForcesXY(int pad, int nXYForce); void SetDeviceForcesXY(int pad, int nXYForce);
HRESULT InitRumble(HWND hWnd); HRESULT InitRumble(HWND hWnd);
void Rumble_DInput(int _ID, unsigned int _Strength); void Rumble_DInput(int _ID, unsigned int _Strength);
void Rumble_XInput(int _ID, unsigned int _Strength); void Rumble_XInput(int _ID, unsigned int _Strength);
LPDIRECTINPUT8 g_Rumble; // DInput Rumble object LPDIRECTINPUT8 g_Rumble; // DInput Rumble object
RUMBLE pRumble[4]; // 4 GC Rumble Pads RUMBLE pRumble[4]; // 4 GC Rumble Pads
void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength) void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
{ {
if (GCMapping[_numPAD].ID >= NumPads || !GCMapping[_numPAD].Rumble) if (GCMapping[_numPAD].ID >= NumPads || !GCMapping[_numPAD].Rumble)
return; return;
unsigned int Strength = 0; unsigned int Strength = 0;
if (_uType == 1 && _uStrength > 2) if (_uType == 1 && _uStrength > 2)
{ {
Strength = GCMapping[_numPAD].RumbleStrength; Strength = GCMapping[_numPAD].RumbleStrength;
Strength = Strength > 100 ? 100 : Strength; Strength = Strength > 100 ? 100 : Strength;
} }
if (GCMapping[_numPAD].TriggerType == InputCommon::CTL_TRIGGER_XINPUT) if (GCMapping[_numPAD].TriggerType == InputCommon::CTL_TRIGGER_XINPUT)
Rumble_XInput(GCMapping[_numPAD].ID, Strength); Rumble_XInput(GCMapping[_numPAD].ID, Strength);
else else
Rumble_DInput(GCMapping[_numPAD].ID, Strength); Rumble_DInput(GCMapping[_numPAD].ID, Strength);
} }
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
// Set rumble with XInput. // Set rumble with XInput.
void Rumble_XInput(int _ID, unsigned int _Strength) void Rumble_XInput(int _ID, unsigned int _Strength)
{ {
#ifdef _WIN32 #ifdef _WIN32
XINPUT_VIBRATION vib; XINPUT_VIBRATION vib;
vib.wLeftMotorSpeed = 0xFFFF / 100 * _Strength; vib.wLeftMotorSpeed = 0xFFFF / 100 * _Strength;
vib.wRightMotorSpeed = 0xFFFF / 100 * _Strength; vib.wRightMotorSpeed = 0xFFFF / 100 * _Strength;
XInputSetState(_ID, &vib); XInputSetState(_ID, &vib);
#endif #endif
} }
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
// Set rumble with DInput.¯¯¯¯¯¯¯¯¯¯¯¯ // Set rumble with DInput.¯¯¯¯¯¯¯¯¯¯¯¯
void Rumble_DInput(int _ID, unsigned int _Strength) void Rumble_DInput(int _ID, unsigned int _Strength)
{ {
if (!g_Rumble) if (!g_Rumble)
{ {
// GetForegroundWindow() always sends the good HWND // GetForegroundWindow() always sends the good HWND
if (FAILED(InitRumble(GetForegroundWindow()))) if (FAILED(InitRumble(GetForegroundWindow())))
PanicAlert("Could not initialize Rumble!"); PanicAlert("Could not initialize Rumble!");
} }
else else
{ {
// Acquire gamepad // Acquire gamepad
if (pRumble[_ID].g_pDevice != NULL) if (pRumble[_ID].g_pDevice != NULL)
pRumble[_ID].g_pDevice->Acquire(); pRumble[_ID].g_pDevice->Acquire();
} }
SetDeviceForcesXY(_ID, _Strength * 100); SetDeviceForcesXY(_ID, _Strength * 100);
} }
HRESULT InitRumble(HWND hWnd) HRESULT InitRumble(HWND hWnd)
{ {
DIPROPDWORD dipdw; DIPROPDWORD dipdw;
HRESULT hr; HRESULT hr;
// Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use. // 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_Rumble, NULL))) if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_Rumble, NULL)))
return hr; return hr;
// Look for a device we can use // Look for a device we can use
if (FAILED(hr = g_Rumble->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, NULL, DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK))) if (FAILED(hr = g_Rumble->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, NULL, DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK)))
return hr; return hr;
for (int i=0; i<4; i++) for (int i=0; i<4; i++)
{ {
if (NULL == pRumble[i].g_pDevice) if (NULL == pRumble[i].g_pDevice)
GCMapping[i].Rumble = false; // Disable Rumble for this pad only. GCMapping[i].Rumble = false; // Disable Rumble for this pad only.
else else
{ {
pRumble[i].g_pDevice->SetDataFormat(&c_dfDIJoystick); pRumble[i].g_pDevice->SetDataFormat(&c_dfDIJoystick);
pRumble[i].g_pDevice->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND); pRumble[i].g_pDevice->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND);
// Request exclusive acces for both background and foreground. // Request exclusive acces for both background and foreground.
dipdw.diph.dwSize = sizeof(DIPROPDWORD); dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0; dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE; dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = FALSE; dipdw.dwData = FALSE;
// if Force Feedback doesn't seem to work... // if Force Feedback doesn't seem to work...
if (FAILED(pRumble[i].g_pDevice->EnumObjects(EnumAxesCallback, if (FAILED(pRumble[i].g_pDevice->EnumObjects(EnumAxesCallback,
(void*)&pRumble[i].g_dwNumForceFeedbackAxis, DIDFT_AXIS)) (void*)&pRumble[i].g_dwNumForceFeedbackAxis, DIDFT_AXIS))
|| FAILED(pRumble[i].g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph))) || FAILED(pRumble[i].g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph)))
{ {
PanicAlert("Device %d doesn't seem to work ! \nRumble for device %d is now Disabled !", i+1); PanicAlert("Device %d doesn't seem to work ! \nRumble for device %d is now Disabled !", i+1);
GCMapping[i].Rumble = false; // Disable Rumble for this pad GCMapping[i].Rumble = false; // Disable Rumble for this pad
continue; // Next pad continue; // Next pad
} }
if (pRumble[i].g_dwNumForceFeedbackAxis > 2) if (pRumble[i].g_dwNumForceFeedbackAxis > 2)
pRumble[i].g_dwNumForceFeedbackAxis = 2; pRumble[i].g_dwNumForceFeedbackAxis = 2;
DWORD _rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y}; DWORD _rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y};
long rglDirection[2] = {0, 0}; long rglDirection[2] = {0, 0};
DICONSTANTFORCE cf = {0}; DICONSTANTFORCE cf = {0};
ZeroMemory(&pRumble[i].eff, sizeof(pRumble[i].eff)); ZeroMemory(&pRumble[i].eff, sizeof(pRumble[i].eff));
pRumble[i].eff.dwSize = sizeof(DIEFFECT); pRumble[i].eff.dwSize = sizeof(DIEFFECT);
pRumble[i].eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; pRumble[i].eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
pRumble[i].eff.dwDuration = INFINITE; // fixed time may be safer (X * DI_SECONDS) pRumble[i].eff.dwDuration = INFINITE; // fixed time may be safer (X * DI_SECONDS)
pRumble[i].eff.dwSamplePeriod = 0; pRumble[i].eff.dwSamplePeriod = 0;
pRumble[i].eff.dwGain = DI_FFNOMINALMAX; pRumble[i].eff.dwGain = DI_FFNOMINALMAX;
pRumble[i].eff.dwTriggerButton = DIEB_NOTRIGGER; pRumble[i].eff.dwTriggerButton = DIEB_NOTRIGGER;
pRumble[i].eff.dwTriggerRepeatInterval = 0; pRumble[i].eff.dwTriggerRepeatInterval = 0;
pRumble[i].eff.cAxes = pRumble[i].g_dwNumForceFeedbackAxis; pRumble[i].eff.cAxes = pRumble[i].g_dwNumForceFeedbackAxis;
pRumble[i].eff.rgdwAxes = _rgdwAxes; pRumble[i].eff.rgdwAxes = _rgdwAxes;
pRumble[i].eff.rglDirection = rglDirection; pRumble[i].eff.rglDirection = rglDirection;
pRumble[i].eff.lpEnvelope = 0; pRumble[i].eff.lpEnvelope = 0;
pRumble[i].eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE ); pRumble[i].eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE );
pRumble[i].eff.lpvTypeSpecificParams = &cf; pRumble[i].eff.lpvTypeSpecificParams = &cf;
pRumble[i].eff.dwStartDelay = 0; pRumble[i].eff.dwStartDelay = 0;
// Create the prepared effect // Create the prepared effect
if (FAILED(hr = pRumble[i].g_pDevice->CreateEffect(GUID_ConstantForce, &pRumble[i].eff, &pRumble[i].g_pEffect, NULL))) if (FAILED(hr = pRumble[i].g_pDevice->CreateEffect(GUID_ConstantForce, &pRumble[i].eff, &pRumble[i].g_pEffect, NULL)))
continue; continue;
if (pRumble[i].g_pEffect == NULL) if (pRumble[i].g_pEffect == NULL)
continue; continue;
} }
} }
return S_OK; return S_OK;
} }
void SetDeviceForcesXY(int npad, int nXYForce) void SetDeviceForcesXY(int npad, int nXYForce)
{ {
// Security check // Security check
if (pRumble[npad].g_pDevice == NULL) if (pRumble[npad].g_pDevice == NULL)
return; return;
// If nXYForce is null, there's no point to create the effect // If nXYForce is null, there's no point to create the effect
// Just stop the force feedback // Just stop the force feedback
if (nXYForce == 0) { if (nXYForce == 0) {
pRumble[npad].g_pEffect->Stop(); pRumble[npad].g_pEffect->Stop();
return; return;
} }
long rglDirection[2] = {0}; long rglDirection[2] = {0};
DICONSTANTFORCE cf; DICONSTANTFORCE cf;
// If only one force feedback axis, then apply only one direction and keep the direction at zero // If only one force feedback axis, then apply only one direction and keep the direction at zero
if (pRumble[npad].g_dwNumForceFeedbackAxis == 1) if (pRumble[npad].g_dwNumForceFeedbackAxis == 1)
{ {
rglDirection[0] = 0; rglDirection[0] = 0;
cf.lMagnitude = nXYForce; // max should be 10000 cf.lMagnitude = nXYForce; // max should be 10000
} }
// If two force feedback axis, then apply magnitude from both directions // If two force feedback axis, then apply magnitude from both directions
else else
{ {
rglDirection[0] = nXYForce; rglDirection[0] = nXYForce;
rglDirection[1] = nXYForce; rglDirection[1] = nXYForce;
cf.lMagnitude = (long)(1.4142f*nXYForce); cf.lMagnitude = (long)(1.4142f*nXYForce);
} }
ZeroMemory(&pRumble[npad].eff, sizeof(pRumble[npad].eff)); ZeroMemory(&pRumble[npad].eff, sizeof(pRumble[npad].eff));
pRumble[npad].eff.dwSize = sizeof(DIEFFECT); pRumble[npad].eff.dwSize = sizeof(DIEFFECT);
pRumble[npad].eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; pRumble[npad].eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
pRumble[npad].eff.cAxes = pRumble[npad].g_dwNumForceFeedbackAxis; pRumble[npad].eff.cAxes = pRumble[npad].g_dwNumForceFeedbackAxis;
pRumble[npad].eff.rglDirection = rglDirection; pRumble[npad].eff.rglDirection = rglDirection;
pRumble[npad].eff.lpEnvelope = 0; pRumble[npad].eff.lpEnvelope = 0;
pRumble[npad].eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); pRumble[npad].eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
pRumble[npad].eff.lpvTypeSpecificParams = &cf; pRumble[npad].eff.lpvTypeSpecificParams = &cf;
pRumble[npad].eff.dwStartDelay = 0; pRumble[npad].eff.dwStartDelay = 0;
// Now set the new parameters.. // Now set the new parameters..
pRumble[npad].g_pEffect->SetParameters(&pRumble[npad].eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START); pRumble[npad].g_pEffect->SetParameters(&pRumble[npad].eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START);
// ..And start the effect immediately. // ..And start the effect immediately.
if (pRumble[npad].g_pEffect != NULL) if (pRumble[npad].g_pEffect != NULL)
pRumble[npad].g_pEffect->Start(1, 0); pRumble[npad].g_pEffect->Start(1, 0);
} }
BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext) BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext)
{ {
LPDIRECTINPUTDEVICE8 pDevice; LPDIRECTINPUTDEVICE8 pDevice;
DIPROPDWORD dipdw; DIPROPDWORD dipdw;
HRESULT hr; HRESULT hr;
int JoystickID; int JoystickID;
dipdw.diph.dwSize = sizeof(DIPROPDWORD); dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0; dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE; dipdw.diph.dwHow = DIPH_DEVICE;
g_Rumble->CreateDevice(pInst->guidInstance, &pDevice, NULL); // Create a DInput pad device g_Rumble->CreateDevice(pInst->guidInstance, &pDevice, NULL); // Create a DInput pad device
if (SUCCEEDED(hr = pDevice->GetProperty(DIPROP_JOYSTICKID, &dipdw.diph))) // Get DInput Device ID if (SUCCEEDED(hr = pDevice->GetProperty(DIPROP_JOYSTICKID, &dipdw.diph))) // Get DInput Device ID
JoystickID = dipdw.dwData; JoystickID = dipdw.dwData;
else else
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
//PanicAlert("DInput ID : %d \nSDL ID (1-4) : %d / %d / %d / %d\n", JoystickID, GCMapping[0].ID, GCMapping[1].ID, GCMapping[2].ID, GCMapping[3].ID); //PanicAlert("DInput ID : %d \nSDL ID (1-4) : %d / %d / %d / %d\n", JoystickID, GCMapping[0].ID, GCMapping[1].ID, GCMapping[2].ID, GCMapping[3].ID);
for (int i=0; i<4; i++) for (int i=0; i<4; i++)
{ {
if (GCMapping[i].ID == JoystickID) // if SDL ID = DInput ID -> we're dealing with the same device if (GCMapping[i].ID == JoystickID) // if SDL ID = DInput ID -> we're dealing with the same device
{ {
// a DInput device is created even if rumble is disabled on startup // a DInput device is created even if rumble is disabled on startup
// this way, you can toggle the rumble setting while in game // this way, you can toggle the rumble setting while in game
pRumble[i].g_pDevice = pDevice; // everything looks good, save the DInput device pRumble[i].g_pDevice = pDevice; // everything looks good, save the DInput device
} }
} }
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
} }
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext) BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext)
{ {
DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; // Enum Rumble Axis DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; // Enum Rumble Axis
if ((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0) if ((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0)
(*pdwNumForceFeedbackAxis)++; (*pdwNumForceFeedbackAxis)++;
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
} }
void PAD_RumbleClose() void PAD_RumbleClose()
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
if (GCMapping[i].ID < NumPads) if (GCMapping[i].ID < NumPads)
if (GCMapping[i].TriggerType == InputCommon::CTL_TRIGGER_XINPUT) if (GCMapping[i].TriggerType == InputCommon::CTL_TRIGGER_XINPUT)
{ {
#ifdef _WIN32 #ifdef _WIN32
// Kill Xpad rumble // Kill Xpad rumble
XINPUT_VIBRATION vib; XINPUT_VIBRATION vib;
vib.wLeftMotorSpeed = 0; vib.wLeftMotorSpeed = 0;
vib.wRightMotorSpeed = 0; vib.wRightMotorSpeed = 0;
XInputSetState(GCMapping[i].ID, &vib); XInputSetState(GCMapping[i].ID, &vib);
#endif #endif
} }
else else
{ {
// It may look weird, but we don't free anything here, it was the cause of crashes // It may look weird, but we don't free anything here, it was the cause of crashes
// on stop, and the DLL isn't unloaded anyway, so the pointers stay // on stop, and the DLL isn't unloaded anyway, so the pointers stay
// We just stop the rumble in case it's still playing an effect. // We just stop the rumble in case it's still playing an effect.
if (pRumble[GCMapping[i].ID].g_pDevice && pRumble[GCMapping[i].ID].g_pEffect) if (pRumble[GCMapping[i].ID].g_pDevice && pRumble[GCMapping[i].ID].g_pEffect)
pRumble[GCMapping[i].ID].g_pEffect->Stop(); pRumble[GCMapping[i].ID].g_pEffect->Stop();
} }
} }
} }
#else // Multiplatform SDL Rumble code #else // Multiplatform SDL Rumble code
#ifdef SDL_RUMBLE #ifdef SDL_RUMBLE
struct RUMBLE // GC Pad rumble DIDevice struct RUMBLE // GC Pad rumble DIDevice
{ {
SDL_Haptic* g_pDevice; SDL_Haptic* g_pDevice;
SDL_HapticEffect g_pEffect; SDL_HapticEffect g_pEffect;
int effect_id; int effect_id;
}; };
RUMBLE pRumble[4] = {0}; // 4 GC Rumble Pads RUMBLE pRumble[4] = {0}; // 4 GC Rumble Pads
#endif #endif
// Use PAD rumble // Use PAD rumble
// -------------- // --------------
bool PAD_Init_Rumble(u8 _numPAD, SDL_Joystick *SDL_Device) bool PAD_Init_Rumble(u8 _numPAD, SDL_Joystick *SDL_Device)
{ {
#ifdef SDL_RUMBLE #ifdef SDL_RUMBLE
if (SDL_Device == NULL) if (SDL_Device == NULL)
return false; return false;
pRumble[_numPAD].g_pDevice = SDL_HapticOpenFromJoystick(SDL_Device); pRumble[_numPAD].g_pDevice = SDL_HapticOpenFromJoystick(SDL_Device);
if (pRumble[_numPAD].g_pDevice == NULL) if (pRumble[_numPAD].g_pDevice == NULL)
return false; // Most likely joystick isn't haptic return false; // Most likely joystick isn't haptic
if (!(SDL_HapticQuery(pRumble[_numPAD].g_pDevice) & SDL_HAPTIC_CONSTANT)) if (!(SDL_HapticQuery(pRumble[_numPAD].g_pDevice) & SDL_HAPTIC_CONSTANT))
{ {
SDL_HapticClose(pRumble[_numPAD].g_pDevice); // No effect SDL_HapticClose(pRumble[_numPAD].g_pDevice); // No effect
pRumble[_numPAD].g_pDevice = 0; pRumble[_numPAD].g_pDevice = 0;
GCMapping[_numPAD].rumble = false; GCMapping[_numPAD].rumble = false;
return false; return false;
} }
// Set the strength of the rumble effect // Set the strength of the rumble effect
int Strenght = 3276 * (g_Config.RumbleStrength + 1); int Strenght = 3276 * (g_Config.RumbleStrength + 1);
Strenght = Strenght > 32767 ? 32767 : Strenght; Strenght = Strenght > 32767 ? 32767 : Strenght;
// Create the effect // Create the effect
memset(&pRumble[_numPAD].g_pEffect, 0, sizeof(SDL_HapticEffect)); // 0 is safe default memset(&pRumble[_numPAD].g_pEffect, 0, sizeof(SDL_HapticEffect)); // 0 is safe default
pRumble[_numPAD].g_pEffect.type = SDL_HAPTIC_CONSTANT; pRumble[_numPAD].g_pEffect.type = SDL_HAPTIC_CONSTANT;
pRumble[_numPAD].g_pEffect.constant.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates pRumble[_numPAD].g_pEffect.constant.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates
pRumble[_numPAD].g_pEffect.constant.direction.dir[0] = 18000; // Force comes from south pRumble[_numPAD].g_pEffect.constant.direction.dir[0] = 18000; // Force comes from south
pRumble[_numPAD].g_pEffect.constant.level = Strenght; pRumble[_numPAD].g_pEffect.constant.level = Strenght;
pRumble[_numPAD].g_pEffect.constant.length = 10000; // 10s long (should be INFINITE, but 10s is safer) pRumble[_numPAD].g_pEffect.constant.length = 10000; // 10s long (should be INFINITE, but 10s is safer)
pRumble[_numPAD].g_pEffect.constant.attack_length = 0; // disable Fade in... pRumble[_numPAD].g_pEffect.constant.attack_length = 0; // disable Fade in...
pRumble[_numPAD].g_pEffect.constant.fade_length = 0; // ...and out pRumble[_numPAD].g_pEffect.constant.fade_length = 0; // ...and out
// Upload the effect // Upload the effect
pRumble[_numPAD].effect_id = SDL_HapticNewEffect( pRumble[_numPAD].g_pDevice, &pRumble[_numPAD].g_pEffect ); pRumble[_numPAD].effect_id = SDL_HapticNewEffect( pRumble[_numPAD].g_pDevice, &pRumble[_numPAD].g_pEffect );
#endif #endif
return true; return true;
} }
// Set PAD rumble. Explanation: Stop = 0, Rumble = 1 // Set PAD rumble. Explanation: Stop = 0, Rumble = 1
// -------------- // --------------
void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength) void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
{ {
int Strenght = 0; int Strenght = 0;
#ifdef SDL_RUMBLE #ifdef SDL_RUMBLE
if (GCMapping[_numPAD].rumble) // rumble activated if (GCMapping[_numPAD].rumble) // rumble activated
{ {
if (!pRumble[_numPAD].g_pDevice) if (!pRumble[_numPAD].g_pDevice)
return; return;
if (_uType == 1 && _uStrength > 2) if (_uType == 1 && _uStrength > 2)
SDL_HapticRunEffect( pRumble[_numPAD].g_pDevice, pRumble[_numPAD].effect_id, 1 ); SDL_HapticRunEffect( pRumble[_numPAD].g_pDevice, pRumble[_numPAD].effect_id, 1 );
else else
SDL_HapticStopAll(pRumble[_numPAD].g_pDevice); SDL_HapticStopAll(pRumble[_numPAD].g_pDevice);
} }
#endif #endif
} }
void PAD_RumbleClose() void PAD_RumbleClose()
{ {
#ifdef SDL_RUMBLE #ifdef SDL_RUMBLE
for (int i=0; i<4; i++) // Free all pads for (int i=0; i<4; i++) // Free all pads
{ {
if (pRumble[i].g_pDevice) { if (pRumble[i].g_pDevice) {
SDL_HapticClose( pRumble[i].g_pDevice ); SDL_HapticClose( pRumble[i].g_pDevice );
pRumble[i].g_pDevice = NULL; pRumble[i].g_pDevice = NULL;
} }
} }
#endif #endif
} }
#endif // RUMBLE_HACK #endif // RUMBLE_HACK

View File

@ -1,28 +1,28 @@
# -*- python -*- # -*- python -*-
Import('env') Import('env')
import sys import sys
name = "Plugin_GCPad" name = "Plugin_GCPad"
padenv = env.Clone() padenv = env.Clone()
if not env['HAVE_SDL']: if not env['HAVE_SDL']:
print name + " must have SDL to be build" print name + " must have SDL to be build"
Return() Return()
files = [ files = [
'Config.cpp', 'Config.cpp',
'GCPad.cpp', 'GCPad.cpp',
'Rumble.cpp', 'Rumble.cpp',
] ]
if padenv['HAVE_WX']: if padenv['HAVE_WX']:
files += [ files += [
'ConfigJoypad.cpp', 'ConfigJoypad.cpp',
'ConfigBox.cpp', 'ConfigBox.cpp',
] ]
padenv.Append( padenv.Append(
LIBS = [ 'inputcommon', 'common', ], LIBS = [ 'inputcommon', 'common', ],
) )
padenv.SharedLibrary(env['plugin_dir']+name, files) padenv.SharedLibrary(env['plugin_dir']+name, files)

View File

@ -315,6 +315,7 @@ void DllConfig(HWND _hParent)
allowConfigShow = m_ConfigFrame->ShowModal() == 1 ? true : false; allowConfigShow = m_ConfigFrame->ShowModal() == 1 ? true : false;
delete m_ConfigFrame; delete m_ConfigFrame;
frame->SetHWND(NULL);
delete frame; delete frame;
m_ConfigFrame = 0; m_ConfigFrame = 0;
} }

View File

@ -188,6 +188,7 @@ void DllConfig(HWND _hParent)
m_BasicConfigFrame->ShowModal(); m_BasicConfigFrame->ShowModal();
m_BasicConfigFrame->Destroy(); m_BasicConfigFrame->Destroy();
m_BasicConfigFrame = NULL; m_BasicConfigFrame = NULL;
frame->SetHWND(NULL);
delete frame; delete frame;
} }
#endif #endif