Warp back to 5578. Sorry for the lost changes, please re-apply. Reason: 5579 is a complete disaster.

Not only does it change tons of files to switch to a new and non-working (it doesn't parse my ini files, at least) ini parser, it also reshuffles a lot of code and removes a plugin. The latter part is fine, but doing these two major switches in one revision, one of which is broken, is completely unacceptable. I said to merge tiny changes, not massive reworkings.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5589 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2010-06-03 18:05:08 +00:00
parent 3236aa9e73
commit a3c96ac42c
118 changed files with 8868 additions and 2530 deletions

View File

@ -2,7 +2,7 @@
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="InputUICommon"
Name="InputPluginCommon"
ProjectGUID="{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}"
RootNamespace="VideoCommon"
Keyword="Win32Proj"
@ -408,18 +408,14 @@
<References>
</References>
<Files>
<Filter
Name="old"
<File
RelativePath=".\Src\Config.cpp"
>
<File
RelativePath=".\Src\WXInputBase.cpp"
>
</File>
<File
RelativePath=".\Src\WXInputBase.h"
>
</File>
</Filter>
</File>
<File
RelativePath=".\Src\Config.h"
>
</File>
<File
RelativePath=".\Src\ConfigDiag.cpp"
>
@ -433,7 +429,19 @@
>
</File>
<File
RelativePath=".\Src\SConscript"
RelativePath=".\Src\ControllerEmu.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerEmu.h"
>
</File>
<File
RelativePath=".\Src\IniFile.cpp"
>
</File>
<File
RelativePath=".\Src\IniFile.h"
>
</File>
</Files>

View File

@ -0,0 +1,57 @@
#include "Config.h"
Plugin::Plugin( const char* const _ini_name, const char* const _gui_name, const char* const _profile_name )
: ini_name(_ini_name)
, gui_name(_gui_name)
, profile_name(_profile_name)
{
// GCPads
//for ( unsigned int i = 0; i<4; ++i )
//controllers.push_back( new GCPad( i ) );
// Wiimotes / disabled, cause it only the GUI half is done
//for ( unsigned int i = 0; i<4; ++i )
// controllers.push_back( new Wiimote( i ) );
};
Plugin::~Plugin()
{
// delete pads
std::vector<ControllerEmu*>::const_iterator i = controllers.begin(),
e = controllers.end();
for ( ; i != e; ++i )
delete *i;
}
void Plugin::LoadConfig()
{
IniFile inifile;
std::ifstream file;
file.open( (std::string(File::GetUserPath(D_CONFIG_IDX)) + ini_name + ".ini" ).c_str() );
inifile.Load( file );
file.close();
std::vector< ControllerEmu* >::const_iterator i = controllers.begin(),
e = controllers.end();
for ( ; i!=e; ++i )
(*i)->LoadConfig( inifile[ (*i)->GetName() ] );
}
void Plugin::SaveConfig()
{
IniFile inifile;
std::vector< ControllerEmu* >::const_iterator i = controllers.begin(),
e = controllers.end();
for ( ; i!=e; ++i )
(*i)->SaveConfig( inifile[ (*i)->GetName() ] );
// dont need to save empty values
//inifile.Clean();
std::ofstream file;
file.open( (std::string(File::GetUserPath(D_CONFIG_IDX)) + ini_name + ".ini" ).c_str() );
inifile.Save( file );
file.close();
}

View File

@ -0,0 +1,36 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include <ControllerInterface/ControllerInterface.h>
#include "Thread.h"
#include "FileUtil.h"
#include "IniFile.h"
#include "ControllerEmu.h"
#include <string>
#include <vector>
#include <map>
#include <sstream>
class Plugin
{
public:
Plugin( const char* const _ini_name, const char* const _gui_name, const char* const _profile_name );
~Plugin();
void LoadConfig();
void SaveConfig();
std::vector< ControllerEmu* > controllers;
Common::CriticalSection controls_crit, interface_crit; // lock controls first
ControllerInterface controller_interface;
const char * const ini_name;
const char * const gui_name;
const char * const profile_name;
};
#endif

View File

@ -3,7 +3,7 @@
#define _connect_macro_( b, f, c, s ) (b)->Connect( wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s );
static Plugin* g_plugin;//WTF?TODOSHUFFLE
static Plugin* g_plugin;
void GamepadPage::ConfigExtension( wxCommandEvent& event )
{
@ -283,7 +283,7 @@ void GamepadPage::ClearAll( wxCommandEvent& event )
g_plugin->controls_crit.Enter(); // enter
// just load an empty ini section to clear everything :P
Section section;
IniSection section;
controller->LoadConfig( section );
// no point in using the real ControllerInterface i guess
@ -516,26 +516,29 @@ ControlChooser::ControlChooser( wxWindow* const parent, ControllerInterface::Con
UpdateListContents();
}
void GamepadPage::LoadProfile(wxCommandEvent& event)
void GamepadPage::LoadProfile( wxCommandEvent& event )
{
// TODO: check for dumb characters maybe
if (profile_cbox->GetValue().empty())
if ( profile_cbox->GetValue().empty() )
return;
g_plugin->controls_crit.Enter();
std::ifstream file;
std::string fname( File::GetUserPath(D_CONFIG_IDX) );
fname += PROFILES_PATH; fname += g_plugin->profile_name; fname += '/';
fname += profile_cbox->GetValue().ToAscii(); fname += ".ini";
if (false == File::Exists(fname.c_str()))
if ( false == File::Exists( fname.c_str() ) )
return;
file.open( fname.c_str() );
IniFile inifile;
inifile.Load(fname);
controller->LoadConfig(inifile["Profile"]);
inifile.Load( file );
controller->LoadConfig( inifile["Profile"] );
file.close();
controller->UpdateReferences(g_plugin->controller_interface);
controller->UpdateReferences( g_plugin->controller_interface );
g_plugin->controls_crit.Leave();
@ -560,7 +563,9 @@ void GamepadPage::SaveProfile( wxCommandEvent& event )
fname += profile_cbox->GetValue().ToAscii(); fname += ".ini";
inifile.Save(fname);
file.open( fname.c_str() );
inifile.Save( file );
file.close();
m_config_dialog->UpdateProfileComboBox();
}

View File

@ -22,7 +22,7 @@
#include <vector>
#include <ControllerInterface/ControllerInterface.h>
#include <InputConfig.h>
#include "Config.h"
#include "FileSearch.h"
class PadSetting

View File

@ -0,0 +1,344 @@
#include "ControllerEmu.h"
#if defined(HAVE_X11) && HAVE_X11
#include <X11/Xlib.h>
#endif
ControllerEmu::~ControllerEmu()
{
// control groups
std::vector<ControlGroup*>::const_iterator
i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
delete *i;
}
ControllerEmu::ControlGroup::~ControlGroup()
{
// controls
std::vector<Control*>::const_iterator
ci = controls.begin(),
ce = controls.end();
for ( ; ci!=ce; ++ci )
delete *ci;
// settings
std::vector<Setting*>::const_iterator
si = settings.begin(),
se = settings.end();
for ( ; si!=se; ++si )
delete *si;
}
ControllerEmu::Extension::~Extension()
{
// attachments
std::vector<ControllerEmu*>::const_iterator
ai = attachments.begin(),
ae = attachments.end();
for ( ; ai!=ae; ++ai )
delete *ai;
}
ControllerEmu::ControlGroup::Control::~Control()
{
delete control_ref;
}
void ControllerEmu::UpdateReferences( ControllerInterface& devi )
{
std::vector<ControlGroup*>::const_iterator
i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
{
std::vector<ControlGroup::Control*>::const_iterator
ci = (*i)->controls.begin(),
ce = (*i)->controls.end();
for ( ; ci!=ce; ++ci )
devi.UpdateReference( (*ci)->control_ref );
// extension
if ( GROUP_TYPE_EXTENSION == (*i)->type )
{
std::vector<ControllerEmu*>::const_iterator
ai = ((Extension*)*i)->attachments.begin(),
ae = ((Extension*)*i)->attachments.end();
for ( ; ai!=ae; ++ai )
(*ai)->UpdateReferences( devi );
}
}
}
void ControllerEmu::UpdateDefaultDevice()
{
std::vector<ControlGroup*>::const_iterator
i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
{
std::vector<ControlGroup::Control*>::const_iterator
ci = (*i)->controls.begin(),
ce = (*i)->controls.end();
for ( ; ci!=ce; ++ci )
(*ci)->control_ref->device_qualifier = default_device;
// extension
if ( GROUP_TYPE_EXTENSION == (*i)->type )
{
std::vector<ControllerEmu*>::const_iterator
ai = ((Extension*)*i)->attachments.begin(),
ae = ((Extension*)*i)->attachments.end();
for ( ; ai!=ae; ++ai )
{
(*ai)->default_device = default_device;
(*ai)->UpdateDefaultDevice();
}
}
}
}
void ControllerEmu::ControlGroup::LoadConfig( IniFile::Section& sec, const std::string& defdev, const std::string& base )
{
std::string group( base + name ); group += "/";
// settings
std::vector<ControlGroup::Setting*>::const_iterator
si = settings.begin(),
se = settings.end();
for ( ; si!=se; ++si )
(*si)->value = sec.Get(group+(*si)->name, (*si)->default_value*100) / 100;
// controls
std::vector<ControlGroup::Control*>::const_iterator
ci = controls.begin(),
ce = controls.end();
for ( ; ci!=ce; ++ci )
{
// control and dev qualifier
(*ci)->control_ref->control_qualifier.name = sec[group + (*ci)->name];
(*ci)->control_ref->device_qualifier.FromString( sec.Get( group+(*ci)->name+"/Device", defdev ) );
// range
(*ci)->control_ref->range = sec.Get( group+(*ci)->name+"/Range", 100.0f ) / 100;
// input mode
if ( (*ci)->control_ref->is_input )
((ControllerInterface::InputReference*)((*ci)->control_ref))->mode
= sec.Get( group+(*ci)->name+"/Mode", 0 );
}
// extensions
if ( GROUP_TYPE_EXTENSION == type )
{
Extension* const ex = ((Extension*)this);
ex->switch_extension = 0;
unsigned int n = 0;
const std::string extname = sec[ base + name ];
std::vector<ControllerEmu*>::const_iterator
ai = ((Extension*)this)->attachments.begin(),
ae = ((Extension*)this)->attachments.end();
for ( ; ai!=ae; ++ai,++n )
{
(*ai)->default_device.FromString( defdev );
(*ai)->LoadConfig( sec, base + (*ai)->GetName() + "/" );
if ( (*ai)->GetName() == extname )
ex->switch_extension = n;
}
}
}
void ControllerEmu::LoadConfig( IniFile::Section& sec, const std::string& base )
{
std::string defdev = default_device.ToString();
if ( base.empty() )
{
defdev = sec[ base + "Device" ];
default_device.FromString( defdev );
}
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
(*i)->LoadConfig( sec, defdev, base );
}
void ControllerEmu::ControlGroup::SaveConfig( IniFile::Section& sec, const std::string& defdev, const std::string& base )
{
std::string group( base + name ); group += "/";
// settings
std::vector<ControlGroup::Setting*>::const_iterator
si = settings.begin(),
se = settings.end();
for ( ; si!=se; ++si )
sec.Set( group+(*si)->name, (*si)->value*100, (*si)->default_value*100 );
// controls
std::vector<ControlGroup::Control*>::const_iterator
ci = controls.begin(),
ce = controls.end();
for ( ; ci!=ce; ++ci )
{
// control and dev qualifier
sec.Set( group+(*ci)->name, (*ci)->control_ref->control_qualifier.name );
sec.Set( group+(*ci)->name+"/Device", (*ci)->control_ref->device_qualifier.ToString(), defdev );
// range
sec.Set( group+(*ci)->name+"/Range", (*ci)->control_ref->range*100, 100 );
// input mode
if ( (*ci)->control_ref->is_input )
sec.Set( group+(*ci)->name+"/Mode",
((ControllerInterface::InputReference*)((*ci)->control_ref))->mode, (unsigned int)0 );
}
// extensions
if ( GROUP_TYPE_EXTENSION == type )
{
Extension* const ext = ((Extension*)this);
sec.Set( base + name, ext->attachments[ext->switch_extension]->GetName(), std::string("None") );
std::vector<ControllerEmu*>::const_iterator
ai = ((Extension*)this)->attachments.begin(),
ae = ((Extension*)this)->attachments.end();
for ( ; ai!=ae; ++ai )
(*ai)->SaveConfig( sec, base + (*ai)->GetName() + "/" );
}
}
void ControllerEmu::SaveConfig( IniFile::Section& sec, const std::string& base )
{
const std::string defdev = default_device.ToString();
if ( base.empty() )
sec.Set( std::string(" ") + base + "Device", defdev );
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
(*i)->SaveConfig( sec, defdev, base );
}
ControllerEmu::AnalogStick::AnalogStick( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_STICK )
{
for ( unsigned int i = 0; i < 4; ++i )
controls.push_back( new Input( named_directions[i] ) );
controls.push_back( new Input( "Modifier" ) );
settings.push_back( new Setting("Dead Zone", 0, 1, 50 ) );
settings.push_back( new Setting("Square Stick", 0 ) );
}
ControllerEmu::Buttons::Buttons( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_BUTTONS )
{
settings.push_back( new Setting("Threshold", 0.5f ) );
}
ControllerEmu::MixedTriggers::MixedTriggers( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_MIXED_TRIGGERS )
{
settings.push_back( new Setting("Threshold", 0.9f ) );
}
ControllerEmu::Triggers::Triggers( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_TRIGGERS )
{
settings.push_back( new Setting("Dead Zone", 0, 1, 50 ) );
}
ControllerEmu::Force::Force( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_FORCE )
{
controls.push_back( new Input( "Up" ) );
controls.push_back( new Input( "Down" ) );
controls.push_back( new Input( "Left" ) );
controls.push_back( new Input( "Right" ) );
controls.push_back( new Input( "Forward" ) );
controls.push_back( new Input( "Backward" ) );
controls.push_back( new Input( "Modifier" ) );
settings.push_back( new Setting("Dead Zone", 0, 1, 50 ) );
}
ControllerEmu::Tilt::Tilt( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_TILT )
{
//for ( unsigned int i = 0; i < 4; ++i )
//controls.push_back( new Input( named_directions[i] ) );
controls.push_back( new Input( "Forward" ) );
controls.push_back( new Input( "Backward" ) );
controls.push_back( new Input( "Left" ) );
controls.push_back( new Input( "Right" ) );
controls.push_back( new Input( "Modifier" ) );
settings.push_back( new Setting("Dead Zone", 0, 1, 50 ) );
settings.push_back( new Setting("Circle Stick", 0 ) );
}
ControllerEmu::Cursor::Cursor( const char* const _name, const SWiimoteInitialize* const _wiimote_initialize )
: ControlGroup( _name, GROUP_TYPE_CURSOR )
//, z(0)
, wiimote_initialize(_wiimote_initialize)
{
for ( unsigned int i = 0; i < 4; ++i )
controls.push_back( new Input( named_directions[i] ) );
controls.push_back( new Input( "Forward" ) );
controls.push_back( new Input( "Hide" ) );
settings.push_back( new Setting("Center", 0.5f ) );
settings.push_back( new Setting("Width", 0.5f ) );
settings.push_back( new Setting("Height", 0.5f ) );
}
void GetMousePos(float& x, float& y, const SWiimoteInitialize* const wiimote_initialize)
{
#if ( defined(_WIN32) || (defined(HAVE_X11) && HAVE_X11))
unsigned int win_width = 2, win_height = 2;
#endif
#ifdef _WIN32
// Get the cursor position for the entire screen
POINT point = { 1, 1 };
GetCursorPos(&point);
// Get the cursor position relative to the upper left corner of the rendering window
ScreenToClient(wiimote_initialize->hWnd, &point);
// Get the size of the rendering window. (In my case Rect.top and Rect.left was zero.)
RECT Rect;
GetClientRect(wiimote_initialize->hWnd, &Rect);
// Width and height is the size of the rendering window
win_width = Rect.right - Rect.left;
win_height = Rect.bottom - Rect.top;
#elif defined(HAVE_X11) && HAVE_X11
int root_x, root_y;
struct
{
int x, y;
} point = { 1, 1 };
Display* const wm_display = (Display*)wiimote_initialize->hWnd;
Window glwin = *(Window *)wiimote_initialize->pXWindow;
XWindowAttributes win_attribs;
XGetWindowAttributes (wm_display, glwin, &win_attribs);
win_width = win_attribs.width;
win_height = win_attribs.height;
Window root_dummy, child_win;
unsigned int mask;
XQueryPointer(wm_display, glwin, &root_dummy, &child_win, &root_x, &root_y, &point.x, &point.y, &mask);
#endif
#if ( defined(_WIN32) || (defined(HAVE_X11) && HAVE_X11))
// Return the mouse position as a range from -1 to 1
x = (float)point.x / (float)win_width * 2 - 1;
y = (float)point.y / (float)win_height * 2 - 1;
#else
x = 0;
y = 0;
#endif
}

View File

@ -0,0 +1,398 @@
#ifndef _CONTROLLEREMU_H_
#define _CONTROLLEREMU_H_
// windows crap
#define NOMINMAX
#include "pluginspecs_pad.h"
#include "pluginspecs_wiimote.h"
//#include <CommonTypes.h>
#include <math.h>
#include <ControllerInterface/ControllerInterface.h>
#include "IniFile.h"
#include <vector>
#include <string>
#include <algorithm>
#define sign(x) ((x)?(x)<0?-1:1:0)
enum
{
GROUP_TYPE_OTHER,
GROUP_TYPE_STICK,
GROUP_TYPE_MIXED_TRIGGERS,
GROUP_TYPE_BUTTONS,
GROUP_TYPE_FORCE,
GROUP_TYPE_EXTENSION,
GROUP_TYPE_TILT,
GROUP_TYPE_CURSOR,
GROUP_TYPE_TRIGGERS,
};
const char * const named_directions[] =
{
"Up",
"Down",
"Left",
"Right"
};
void GetMousePos(float& x, float& y, const SWiimoteInitialize* const wiimote_initialize);
class ControllerEmu
{
public:
class ControlGroup
{
public:
class Control
{
protected:
Control( ControllerInterface::ControlReference* const _ref, const char * const _name )
: control_ref(_ref), name(_name){}
public:
virtual ~Control();
ControllerInterface::ControlReference* const control_ref;
const char * const name;
};
class Input : public Control
{
public:
Input( const char * const _name )
: Control( new ControllerInterface::InputReference, _name ) {}
};
class Output : public Control
{
public:
Output( const char * const _name )
: Control( new ControllerInterface::OutputReference, _name ) {}
};
class Setting
{
public:
Setting(const char* const _name, const ControlState def_value
, const unsigned int _low = 1, const unsigned int _high = 100 )
: name(_name)
, value(def_value)
, default_value(def_value)
, low(_low)
, high(_high){}
const char* const name;
ControlState value;
const ControlState default_value;
const unsigned int low, high;
};
ControlGroup( const char* const _name, const unsigned int _type = GROUP_TYPE_OTHER ) : name(_name), type(_type) {}
virtual ~ControlGroup();
void LoadConfig( IniFile::Section& sec, const std::string& defdev = "", const std::string& base = "" );
void SaveConfig( IniFile::Section& sec, const std::string& defdev = "", const std::string& base = "" );
const char* const name;
const unsigned int type;
std::vector< Control* > controls;
std::vector< Setting* > settings;
};
class AnalogStick : public ControlGroup
{
public:
template <typename C>
void GetState( C* const x, C* const y, const unsigned int base, const unsigned int range )
{
// this is all a mess
ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
ControlState deadzone = settings[0]->value;
ControlState square = settings[1]->value;
ControlState m = controls[4]->control_ref->State();
// modifier code
if ( m )
{
yy = (abs(yy)>deadzone) * sign(yy) * (m + deadzone/2);
xx = (abs(xx)>deadzone) * sign(xx) * (m + deadzone/2);
}
// deadzone / square stick code
if ( deadzone || square )
{
// this section might be all wrong, but its working good enough, i think
ControlState ang = atan2( yy, xx );
ControlState ang_sin = sin(ang);
ControlState ang_cos = cos(ang);
// the amt a full square stick would have at current angle
ControlState square_full = std::min( ang_sin ? 1/abs(ang_sin) : 2, ang_cos ? 1/abs(ang_cos) : 2 );
// the amt a full stick would have that was ( user setting squareness) at current angle
// i think this is more like a pointed circle rather than a rounded square like it should be
ControlState stick_full = ( 1 + ( square_full - 1 ) * square );
ControlState dist = sqrt(xx*xx + yy*yy);
// dead zone code
dist = std::max( 0.0f, dist - deadzone * stick_full );
dist /= ( 1 - deadzone );
// square stick code
ControlState amt = dist / stick_full;
dist -= ((square_full - 1) * amt * square);
yy = std::max( -1.0f, std::min( 1.0f, ang_sin * dist ) );
xx = std::max( -1.0f, std::min( 1.0f, ang_cos * dist ) );
}
*y = C( yy * range + base );
*x = C( xx * range + base );
}
AnalogStick( const char* const _name );
};
class Buttons : public ControlGroup
{
public:
Buttons( const char* const _name );
template <typename C>
void GetState( C* const buttons, const C* bitmasks )
{
std::vector<Control*>::iterator i = controls.begin(),
e = controls.end();
for ( ; i!=e; ++i, ++bitmasks )
if ( (*i)->control_ref->State() > settings[0]->value ) // threshold
*buttons |= *bitmasks;
}
};
class MixedTriggers : public ControlGroup
{
public:
template <typename C, typename S>
void GetState( C* const digital, const C* bitmasks, S* analog, const unsigned int range )
{
const unsigned int trig_count = ((unsigned int) (controls.size() / 2));
for ( unsigned int i=0; i<trig_count; ++i,++bitmasks,++analog )
{
if ( controls[i]->control_ref->State() > settings[0]->value ) //threshold
{
*analog = range;
*digital |= *bitmasks;
}
else
*analog = S(controls[i+trig_count]->control_ref->State() * range);
}
}
MixedTriggers( const char* const _name );
};
class Triggers : public ControlGroup
{
public:
template <typename S>
void GetState( S* analog, const unsigned int range )
{
const unsigned int trig_count = ((unsigned int) (controls.size()));
const ControlState deadzone = settings[0]->value;
for ( unsigned int i=0; i<trig_count; ++i,++analog )
*analog = S( std::max(controls[i]->control_ref->State() - deadzone, 0.0f) / (1 - deadzone) * range );
}
Triggers( const char* const _name );
};
class Force : public ControlGroup
{
public:
Force( const char* const _name );
template <typename C, typename R>
void GetState( C* axis, const u8 base, const R range )
{
const float deadzone = settings[0]->value;
for ( unsigned int i=0; i<6; i+=2 )
{
const float state = controls[i+1]->control_ref->State() - controls[i]->control_ref->State();
if (abs(state) > deadzone)
*axis++ = (C)((state - (deadzone * sign(state))) / (1 - deadzone) * range + base);
//*axis++ = state * range + base;
else
*axis++ = (C)(base);
}
}
};
class Tilt : public ControlGroup
{
public:
Tilt( const char* const _name );
template <typename C, typename R>
void GetState( C* const x, C* const y, const unsigned int base, const R range )
{
// this is all a mess
ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
ControlState deadzone = settings[0]->value;
ControlState circle = settings[1]->value;
ControlState m = controls[4]->control_ref->State();
// modifier code
if ( m )
{
yy = (abs(yy)>deadzone) * sign(yy) * (m + deadzone/2);
xx = (abs(xx)>deadzone) * sign(xx) * (m + deadzone/2);
}
// deadzone / circle stick code
if ( deadzone || circle )
{
// this section might be all wrong, but its working good enough, i think
ControlState ang = atan2( yy, xx );
ControlState ang_sin = sin(ang);
ControlState ang_cos = cos(ang);
// the amt a full square stick would have at current angle
ControlState square_full = std::min( ang_sin ? 1/abs(ang_sin) : 2, ang_cos ? 1/abs(ang_cos) : 2 );
// the amt a full stick would have that was ( user setting circular ) at current angle
// i think this is more like a pointed circle rather than a rounded square like it should be
ControlState stick_full = (square_full * (1 - circle)) + (circle);
ControlState dist = sqrt(xx*xx + yy*yy);
// dead zone code
dist = std::max( 0.0f, dist - deadzone * stick_full );
dist /= (1 - deadzone);
// circle stick code
ControlState amt = dist / stick_full;
dist += (square_full - 1) * amt * circle;
yy = std::max( -1.0f, std::min( 1.0f, ang_sin * dist ) );
xx = std::max( -1.0f, std::min( 1.0f, ang_cos * dist ) );
}
*y = C( yy * range + base );
*x = C( xx * range + base );
}
};
class Cursor : public ControlGroup
{
public:
Cursor( const char* const _name, const SWiimoteInitialize* const _wiimote_initialize );
template <typename C>
void GetState( C* const x, C* const y, C* const forward, const bool adjusted = false )
{
const ControlState z = controls[4]->control_ref->State();
// hide
if (controls[5]->control_ref->State() > 0.5f)
{
*x = 10000; *y = 0; *forward = 0;
}
else
{
*forward = z;
float xx, yy;
GetMousePos(xx, yy, wiimote_initialize);
// use mouse cursor, or user defined mapping if they have something mapped
// this if seems horrible
if ( controls[0]->control_ref->control_qualifier.name.size() || controls[1]->control_ref->control_qualifier.name.size() )
yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
else
yy = -yy;
if ( controls[2]->control_ref->control_qualifier.name.size() || controls[3]->control_ref->control_qualifier.name.size() )
xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
// adjust cursor according to settings
if (adjusted)
{
xx *= ( settings[1]->value * 2 );
yy *= ( settings[2]->value * 2 );
yy += ( settings[0]->value - 0.5f );
}
*x = xx;
*y = yy;
}
}
private:
const SWiimoteInitialize* const wiimote_initialize;
};
class Extension : public ControlGroup
{
public:
Extension( const char* const _name )
: ControlGroup( _name, GROUP_TYPE_EXTENSION )
, switch_extension(0)
, active_extension(0) {}
~Extension();
void GetState( u8* const data, const bool focus = true );
std::vector<ControllerEmu*> attachments;
int switch_extension;
int active_extension;
};
virtual ~ControllerEmu();
virtual std::string GetName() const = 0;
void LoadConfig( IniFile::Section& sec, const std::string& base = "" );
void SaveConfig( IniFile::Section& sec, const std::string& base = "" );
void UpdateDefaultDevice();
void UpdateReferences( ControllerInterface& devi );
std::vector< ControlGroup* > groups;
ControllerInterface::DeviceQualifier default_device;
};
#endif

View File

@ -0,0 +1,156 @@
#include "IniFile.h"
//
// TrimChars
//
// trim whitespace, or any, chars from both ends
//
template <typename S>
std::string TrimChars( const std::string& str, const S space )
{
const size_t start = str.find_first_not_of( space );
if ( str.npos == start )
return "";
return str.substr( start, str.find_last_not_of( space ) - start + 1 );
}
//
// IniSection :: Set
//
// set key's value if it doesn't match the default
// otherwise remove the key from the section if it exists
//
void IniSection::Set( const std::string& key, const std::string& val, const std::string& def )
{
if ( val != def )
operator[](key) = val;
else
{
iterator f = find(key);
if ( f != end() )
erase( f );
}
}
//
// IniSection :: Get
//
// return a key's value if it exists
// otherwise return the default
//
std::string IniSection::Get( const std::string& key, const std::string& def )
{
const const_iterator f = find(key);
if ( f != end() )
if ( false == f->second.empty() )
return f->second;
return def;
}
//
// IniFile :: Save
//
// save a file
//
void IniFile::Save( std::ostream& file )
{
const_iterator i = begin(),
e = end();
for ( ; i != e; ++i )
{
// skip a line at new sections
file << "\n[" << i->first << "]\n";
Section::const_iterator si = i->second.begin(),
se = i->second.end();
for ( ; si != se; ++si )
{
file << si->first << " = ";
// if value has quotes or whitespace, surround it with quotes
if (si->second.find_first_of("\"\t ") != std::string::npos)
file << '"' << si->second << '"';
else
file << si->second;
file << '\n';
}
}
}
//
// IniFile :: Load
//
// load a file
//
void IniFile::Load( std::istream& file )
{
const char* const space = "\t\r ";
std::string line;
// start off with an empty section
Section* section = &(*this)[""];
while ( std::getline( file, line ).good() ) // read a line
{
line = TrimChars(line,space);
if ( line.size() )
{
switch ( line[0] )
{
// comment
case '#' :
case ';' :
break;
// section
case '[' :
// kinda odd trimming
section = &(*this)[ TrimChars(line,"][\t\r ") ];
break;
// key/value
default :
{
std::istringstream ss(line);
std::string key; std::getline( ss, key, '=' );
std::string val; std::getline( ss, val );
val = TrimChars(val,space);
// handle quote surrounded values
if (val.length() > 1)
if ('"' == val[0])
val = val.substr(1, val.length()-2);
(*section)[ TrimChars(key,space) ] = val;
break;
}
}
}
}
Clean();
}
//
// IniFile :: Clean
//
// remove empty key/values and sections
// after trying to access ini sections/values, they are automatically allocated
// this deletes the empty stuff
//
void IniFile::Clean()
{
iterator i = begin(),
e = end();
for ( ; i != e; )
{
Section::iterator si = i->second.begin(),
se = i->second.end();
for ( ; si != se; )
{
if ( si->second.empty() )
i->second.erase( si++ );
else
++si;
}
if ( i->second.empty() )
erase( i++ );
else
++i;
}
}

View File

@ -0,0 +1,61 @@
#ifndef _INIFILE_H_
#define _INIFILE_H_
#include <fstream>
#include <map>
#include <string>
#include <sstream>
//
// IniFile
//
class IniSection : public std::map< std::string, std::string >
{
public:
void Set( const std::string& key, const std::string& val, const std::string& def = "" );
std::string Get( const std::string& key, const std::string& def = "" );
template <typename V, typename D>
void Set( const std::string& key, const V& val, const D& def = 0 )
{
if ( val != def )
{
std::ostringstream ss;
ss << long(val);
operator[](key) = ss.str();
}
else
{
iterator f = find(key);
if ( f != end() )
erase( f );
}
}
template <typename V>
V Get( const std::string& key, const V& def = 0 )
{
const const_iterator f = find(key);
if ( f != end() )
if ( false == f->second.empty() )
{
std::istringstream ss(f->second);
int val;
ss >> val;
return V(val);
}
return def;
}
};
class IniFile : public std::map< std::string, IniSection >
{
public:
typedef IniSection Section;
void Clean();
void Save( std::ostream& file );
void Load( std::istream& file );
};
#endif

View File

@ -0,0 +1,20 @@
# -*- python -*-
Import('env')
files = [
'Config.cpp',
'ControllerEmu.cpp',
'IniFile.cpp',
]
if env['HAVE_WX']:
files += [
'ConfigDiagBitmaps.cpp',
'ConfigDiag.cpp',
]
env_inputpc = env.Clone()
env_inputpc.StaticLibrary(env['local_libs'] + "inputplugincommon", files)

View File

@ -1,13 +0,0 @@
# -*- python -*-
Import('env')
if env['HAVE_WX']:
files = [
'ConfigDiagBitmaps.cpp',
'ConfigDiag.cpp',
'WXInputBase.cpp'
]
env_inputpc = env.Clone()
env_inputpc.StaticLibrary(env['local_libs'] + "inputuicommon", files)

View File

@ -1,127 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <wx/stattext.h>
#include "WXInputBase.h"
//#include <string.h>
//#include <stdio.h>
//#include <ctype.h>
namespace InputCommon
{
const wxChar *WXKeyToString(int keycode)
{
switch (keycode)
{
case WXK_CANCEL: return wxT("Cancel"); break;
case WXK_BACK: return wxT("Back"); break;
case WXK_TAB: return wxT("Tab"); break;
case WXK_CLEAR: return wxT("Clear"); break;
case WXK_RETURN: return wxT("Return"); break;
case WXK_SHIFT: return wxT("Shift"); break;
case WXK_CONTROL: return wxT("Control"); break;
case WXK_ALT: return wxT("Alt"); break;
case WXK_CAPITAL: return wxT("CapsLock"); break;
case WXK_MENU : return wxT("Menu"); break;
case WXK_PAUSE: return wxT("Pause"); break;
case WXK_ESCAPE: return wxT("Escape"); break;
case WXK_SPACE: return wxT("Space"); break;
case WXK_PAGEUP: return wxT("PgUp"); break;
case WXK_PAGEDOWN: return wxT("PgDn"); break;
case WXK_END: return wxT("End"); break;
case WXK_HOME : return wxT("Home"); break;
case WXK_LEFT : return wxT("Left"); break;
case WXK_UP: return wxT("Up"); break;
case WXK_RIGHT: return wxT("Right"); break;
case WXK_DOWN : return wxT("Down"); break;
case WXK_SELECT: return wxT("Select"); break;
case WXK_PRINT: return wxT("Print"); break;
case WXK_EXECUTE: return wxT("Execute"); break;
case WXK_INSERT: return wxT("Insert"); break;
case WXK_DELETE: return wxT("Delete"); break;
case WXK_HELP : return wxT("Help"); break;
case WXK_NUMPAD0: return wxT("NP 0"); break;
case WXK_NUMPAD1: return wxT("NP 1"); break;
case WXK_NUMPAD2: return wxT("NP 2"); break;
case WXK_NUMPAD3: return wxT("NP 3"); break;
case WXK_NUMPAD4: return wxT("NP 4"); break;
case WXK_NUMPAD5: return wxT("NP 5"); break;
case WXK_NUMPAD6: return wxT("NP 6"); break;
case WXK_NUMPAD7: return wxT("NP 7"); break;
case WXK_NUMPAD8: return wxT("NP 8"); break;
case WXK_NUMPAD9: return wxT("NP 9"); break;
case WXK_NUMPAD_DECIMAL: return wxT("NP ."); break;
case WXK_NUMPAD_DELETE: return wxT("NP Delete"); break;
case WXK_NUMPAD_INSERT: return wxT("NP Insert"); break;
case WXK_NUMPAD_END: return wxT("NP End"); break;
case WXK_NUMPAD_DOWN: return wxT("NP Down"); break;
case WXK_NUMPAD_PAGEDOWN: return wxT("NP Pagedown"); break;
case WXK_NUMPAD_LEFT: return wxT("NP Left"); break;
case WXK_NUMPAD_RIGHT: return wxT("NP Right"); break;
case WXK_NUMPAD_HOME: return wxT("NP Home"); break;
case WXK_NUMPAD_UP: return wxT("NP Up"); break;
case WXK_NUMPAD_PAGEUP: return wxT("NP Pageup"); break;
case WXK_NUMPAD_MULTIPLY: return wxT("NP *"); break;
case WXK_NUMPAD_ADD: return wxT("NP +"); break;
case WXK_NUMPAD_SUBTRACT: return wxT("NP -"); break;
case WXK_NUMPAD_DIVIDE: return wxT("NP /"); break;
case WXK_NUMPAD_ENTER: return wxT("NP Enter"); break;
case WXK_NUMPAD_SEPARATOR: return wxT("NP Separator"); break;
case WXK_F1: return wxT("F1"); break;
case WXK_F2: return wxT("F2"); break;
case WXK_F3: return wxT("F3"); break;
case WXK_F4: return wxT("F4"); break;
case WXK_F5: return wxT("F5"); break;
case WXK_F6: return wxT("F6"); break;
case WXK_F7: return wxT("F7"); break;
case WXK_F8: return wxT("F8"); break;
case WXK_F9: return wxT("F9"); break;
case WXK_F10: return wxT("F10"); break;
case WXK_F11: return wxT("F11"); break;
case WXK_F12: return wxT("F12"); break;
case WXK_F13: return wxT("F13"); break;
case WXK_F14: return wxT("F14"); break;
case WXK_F15: return wxT("F15"); break;
case WXK_F16: return wxT("F16"); break;
case WXK_F17: return wxT("F17"); break;
case WXK_F18: return wxT("F19"); break;
case WXK_F19: return wxT("F20"); break;
case WXK_F20: return wxT("F21"); break;
case WXK_F21: return wxT("F22"); break;
case WXK_F22: return wxT("F23"); break;
case WXK_F23: return wxT("F24"); break;
case WXK_F24: return wxT("F25"); break;
case WXK_NUMLOCK: return wxT("Numlock"); break;
case WXK_SCROLL: return wxT("Scrolllock"); break;
default: return wxString::FromAscii(keycode);
}
}
const wxChar *WXKeymodToString(int modifier)
{
switch (modifier)
{
case wxMOD_ALT: return wxT("Alt"); break;
case wxMOD_CMD: return wxT("Ctrl"); break;
case wxMOD_ALTGR: return wxT("Ctrl+Alt"); break;
case wxMOD_SHIFT: return wxT("Shift"); break;
default: return wxT(""); break;
}
}
}

View File

@ -34,7 +34,7 @@ void CConfig::Load()
// first load defaults
IniFile file;
file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "DSP.ini").c_str());
file["Config"].Get("EnableHLEAudio", &m_EnableHLEAudio, true); // Sound Settings
file.Get("Config", "EnableHLEAudio", &m_EnableHLEAudio, true); // Sound Settings
ac_Config.Load(file);
}
@ -42,7 +42,7 @@ void CConfig::Save()
{
IniFile file;
file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "DSP.ini").c_str());
file["Config"].Set("EnableHLEAudio", m_EnableHLEAudio); // Sound Settings
file.Set("Config", "EnableHLEAudio", m_EnableHLEAudio); // Sound Settings
ac_Config.Set(file);
file.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "DSP.ini").c_str());

View File

@ -0,0 +1,559 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="Plugin_GCPad"
ProjectGUID="{9FF603F8-B3BB-4144-9688-B2B802FA0F16}"
RootNamespace="Plugin_nJoy_SDL"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
WarnAsError="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="SDL.lib comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\$(ProjectName)D.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
WarnAsError="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="SDL.lib comctl32.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\$(ProjectName).dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugFast|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;DEBUGFAST;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
WarnAsError="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="SDL.lib comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\$(ProjectName)DF.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="SDL.lib comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName)D.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="SDL.lib comctl32.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName).dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugFast|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;DEBUGFAST;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="SDL.lib comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName)DF.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Config"
>
<File
RelativePath=".\Src\Config.cpp"
>
</File>
<File
RelativePath=".\Src\Config.h"
>
</File>
<File
RelativePath=".\Src\ConfigBox.cpp"
>
</File>
<File
RelativePath=".\Src\ConfigBox.h"
>
</File>
<File
RelativePath=".\Src\ConfigJoypad.cpp"
>
</File>
</Filter>
<File
RelativePath=".\Src\GCPad.cpp"
>
</File>
<File
RelativePath=".\Src\GCPad.h"
>
</File>
<File
RelativePath="..\..\PluginSpecs\pluginspecs_pad.h"
>
</File>
<File
RelativePath=".\Src\ReRecording.cpp"
>
</File>
<File
RelativePath=".\Src\Rumble.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

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

View File

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

View File

@ -0,0 +1,823 @@
// Project description
// -------------------
// Name: nJoy
// Description: A Dolphin Compatible Input Plugin
//
// Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project.
//
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "math.h" // System
#include "ConfigBox.h"
#include "Config.h"
#include "GCPad.h"
#if defined(HAVE_X11) && HAVE_X11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/XKBlib.h>
#include "X11InputBase.h"
#endif
// The wxWidgets class
BEGIN_EVENT_TABLE(GCPadConfigDialog,wxDialog)
EVT_CLOSE(GCPadConfigDialog::OnClose)
EVT_BUTTON(wxID_OK, GCPadConfigDialog::OnCloseClick)
EVT_BUTTON(wxID_CANCEL, GCPadConfigDialog::OnCloseClick)
EVT_NOTEBOOK_PAGE_CHANGED(ID_NOTEBOOK, GCPadConfigDialog::NotebookPageChanged)
EVT_CHOICE(IDC_JOYNAME, GCPadConfigDialog::ChangeSettings)
EVT_CHECKBOX(IDC_RUMBLE, GCPadConfigDialog::ChangeSettings)
EVT_CHOICE(IDC_RUMBLE_STRENGTH, GCPadConfigDialog::ChangeSettings)
EVT_CHOICE(IDC_DEAD_ZONE_LEFT, GCPadConfigDialog::ChangeSettings)
EVT_CHOICE(IDC_DEAD_ZONE_RIGHT, GCPadConfigDialog::ChangeSettings)
EVT_CHOICE(IDC_STICK_DIAGONAL, GCPadConfigDialog::ChangeSettings)
EVT_CHECKBOX(IDC_STICK_S2C, GCPadConfigDialog::ChangeSettings)
EVT_CHOICE(IDC_TRIGGER_TYPE, GCPadConfigDialog::ChangeSettings)
EVT_CHOICE(IDC_STICK_SOURCE, GCPadConfigDialog::ChangeSettings)
EVT_CHOICE(IDC_CSTICK_SOURCE, GCPadConfigDialog::ChangeSettings)
EVT_CHOICE(IDC_TRIGGER_SOURCE, GCPadConfigDialog::ChangeSettings)
EVT_SLIDER(IDS_STICK_PRESS, GCPadConfigDialog::ChangeSettings)
EVT_SLIDER(IDS_CSTICK_PRESS, GCPadConfigDialog::ChangeSettings)
EVT_SLIDER(IDS_TRIGGER_PRESS, GCPadConfigDialog::ChangeSettings)
EVT_BUTTON(IDB_ANALOG_LEFT_X, GCPadConfigDialog::OnAxisClick)
EVT_BUTTON(IDB_ANALOG_LEFT_Y, GCPadConfigDialog::OnAxisClick)
EVT_BUTTON(IDB_ANALOG_RIGHT_X, GCPadConfigDialog::OnAxisClick)
EVT_BUTTON(IDB_ANALOG_RIGHT_Y, GCPadConfigDialog::OnAxisClick)
EVT_BUTTON(IDB_TRIGGER_L, GCPadConfigDialog::OnAxisClick)
EVT_BUTTON(IDB_TRIGGER_R, GCPadConfigDialog::OnAxisClick)
EVT_BUTTON(IDB_BTN_A, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_BTN_B, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_BTN_X, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_BTN_Y, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_BTN_Z, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_BTN_START, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_DPAD_UP, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_DPAD_DOWN, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_DPAD_LEFT, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_DPAD_RIGHT, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_MAIN_UP, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_MAIN_DOWN, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_MAIN_LEFT, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_MAIN_RIGHT, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_MAIN_SEMI, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_SUB_UP, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_SUB_DOWN, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_SUB_LEFT, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_SUB_RIGHT, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_SUB_SEMI, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_SHDR_L, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_SHDR_R, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_SHDR_SEMI_L, GCPadConfigDialog::OnButtonClick)
EVT_BUTTON(IDB_SHDR_SEMI_R, GCPadConfigDialog::OnButtonClick)
#if wxUSE_TIMER
EVT_TIMER(IDTM_UPDATE_PAD, GCPadConfigDialog::UpdatePadInfo)
EVT_TIMER(IDTM_BUTTON, GCPadConfigDialog::OnButtonTimer)
#endif
END_EVENT_TABLE()
GCPadConfigDialog::GCPadConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title,
const wxPoint &position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style)
{
// Define values
m_ControlsCreated = false;
m_Page = 0;
// Create controls
CreateGUIControls();
#if wxUSE_TIMER
m_UpdatePadTimer = new wxTimer(this, IDTM_UPDATE_PAD);
m_ButtonMappingTimer = new wxTimer(this, IDTM_BUTTON);
// Reset values
g_Pressed = 0;
ClickedButton = NULL;
GetButtonWaitingID = 0;
GetButtonWaitingTimer = 0;
if (NumGoodPads)
{
// Start the constant timer
int TimesPerSecond = 10;
m_UpdatePadTimer->Start(1000 / TimesPerSecond);
}
#endif
UpdateGUI();
}
GCPadConfigDialog::~GCPadConfigDialog()
{
if (m_ButtonMappingTimer)
{
delete m_ButtonMappingTimer;
m_ButtonMappingTimer = NULL;
}
if (m_UpdatePadTimer)
{
delete m_UpdatePadTimer;
m_UpdatePadTimer = NULL;
}
}
// Notebook page changed
void GCPadConfigDialog::NotebookPageChanged(wxNotebookEvent& event)
{
// Update the global variable
m_Page = event.GetSelection();
// Update GUI
UpdateGUI();
}
// Close window
void GCPadConfigDialog::OnClose(wxCloseEvent& event)
{
// Allow wxWidgets to close the window
//event.Skip();
// Stop the timer
if (m_UpdatePadTimer)
m_UpdatePadTimer->Stop();
if (m_ButtonMappingTimer)
m_ButtonMappingTimer->Stop();
EndModal(wxID_CLOSE);
}
// Button Click
void GCPadConfigDialog::OnCloseClick(wxCommandEvent& event)
{
switch (event.GetId())
{
case wxID_OK:
g_Config.Save();
Close(); // Call OnClose()
break;
case wxID_CANCEL:
g_Config.Load();
Close(); // Call OnClose()
break;
}
}
void GCPadConfigDialog::SaveButtonMapping(int Id, int Key)
{
if (IDB_ANALOG_LEFT_X <= Id && Id <= IDB_TRIGGER_R)
{
GCMapping[m_Page].AxisMapping.Code[Id - IDB_ANALOG_LEFT_X] = Key;
}
else if (IDB_BTN_A <= Id && Id <= IDB_SHDR_SEMI_R)
{
GCMapping[m_Page].Button[Id - IDB_BTN_A] = Key;
}
}
void GCPadConfigDialog::OnKeyDown(wxKeyEvent& event)
{
//event.Skip();
if(ClickedButton != NULL)
{
// Save the key
g_Pressed = event.GetKeyCode();
// Handle the keyboard key mapping
// Allow the escape key to set a blank key
if (g_Pressed == WXK_ESCAPE)
{
SaveButtonMapping(ClickedButton->GetId(), -1);
SetButtonText(ClickedButton->GetId(), wxString());
}
else
{
#ifdef _WIN32
BYTE keyState[256];
GetKeyboardState(keyState);
for (int i = 1; i < 256; ++i)
{
if ((keyState[i] & 0x80) != 0)
{
// Use the left and right specific keys instead of the common ones
if (i == VK_SHIFT || i == VK_CONTROL || i == VK_MENU) continue;
// Update the button label
SetButtonText(ClickedButton->GetId(),
wxString::FromAscii(InputCommon::VKToString(i).c_str()));
// Save the setting
SaveButtonMapping(ClickedButton->GetId(), i);
break;
}
}
#elif defined(HAVE_X11) && HAVE_X11
char keyStr[128] = {0};
int XKey = InputCommon::wxCharCodeWXToX(g_Pressed);
InputCommon::XKeyToString(XKey, keyStr);
SetButtonText(ClickedButton->GetId(),
wxString::FromAscii(keyStr));
SaveButtonMapping(ClickedButton->GetId(), XKey);
#endif
}
EndGetButtons();
}
}
// Configure button mapping
void GCPadConfigDialog::OnButtonClick(wxCommandEvent& event)
{
event.Skip();
// Don't allow space to start a new Press Key option, that will interfer with setting a key to space
if (g_Pressed == WXK_SPACE) { g_Pressed = 0; return; }
if (m_ButtonMappingTimer->IsRunning()) return;
wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
wxKeyEventHandler(GCPadConfigDialog::OnKeyDown),
(wxObject*)0, this);
// Create the button object
ClickedButton = (wxButton *)event.GetEventObject();
// Save old label so we can revert back
OldLabel = ClickedButton->GetLabel();
ClickedButton->SetWindowStyle(wxWANTS_CHARS);
ClickedButton->SetLabel(wxT("<Press Key>"));
DoGetButtons(ClickedButton->GetId());
}
// Configure axis mapping
void GCPadConfigDialog::OnAxisClick(wxCommandEvent& event)
{
event.Skip();
if (m_ButtonMappingTimer->IsRunning()) return;
ClickedButton = NULL;
wxButton* pButton = (wxButton *)event.GetEventObject();
OldLabel = pButton->GetLabel();
pButton->SetWindowStyle(wxWANTS_CHARS);
pButton->SetLabel(wxT("<Move Axis>"));
DoGetButtons(pButton->GetId());
}
void GCPadConfigDialog::ChangeSettings(wxCommandEvent& event)
{
int id = event.GetId();
switch (id)
{
case IDC_JOYNAME:
GCMapping[m_Page].ID = m_Joyname[m_Page]->GetSelection();
GCMapping[m_Page].joy = joyinfo.at(GCMapping[m_Page].ID).joy;
break;
case IDC_DEAD_ZONE_LEFT:
GCMapping[m_Page].DeadZoneL = m_ComboDeadZoneLeft[m_Page]->GetSelection();
break;
case IDC_DEAD_ZONE_RIGHT:
GCMapping[m_Page].DeadZoneR = m_ComboDeadZoneRight[m_Page]->GetSelection();
break;
case IDC_STICK_DIAGONAL:
GCMapping[m_Page].Diagonal = 100 - m_ComboDiagonal[m_Page]->GetSelection() * 5;
break;
case IDC_STICK_S2C:
GCMapping[m_Page].bSquare2Circle = m_CheckS2C[m_Page]->IsChecked();
break;
case IDC_RUMBLE:
GCMapping[m_Page].Rumble = m_CheckRumble[m_Page]->IsChecked();
break;
case IDC_RUMBLE_STRENGTH:
GCMapping[m_Page].RumbleStrength = m_RumbleStrength[m_Page]->GetSelection() * 10;
break;
case IDC_TRIGGER_TYPE:
GCMapping[m_Page].TriggerType = m_TriggerType[m_Page]->GetSelection();
break;
case IDC_STICK_SOURCE:
GCMapping[m_Page].Stick.Main = m_Combo_StickSrc[m_Page]->GetSelection();
break;
case IDC_CSTICK_SOURCE:
GCMapping[m_Page].Stick.Sub = m_Combo_CStickSrc[m_Page]->GetSelection();
break;
case IDC_TRIGGER_SOURCE:
GCMapping[m_Page].Stick.Shoulder = m_Combo_TriggerSrc[m_Page]->GetSelection();
break;
case IDS_STICK_PRESS:
GCMapping[m_Page].Pressure.Main = m_Slider_Stick[m_Page]->GetValue();
break;
case IDS_CSTICK_PRESS:
GCMapping[m_Page].Pressure.Sub = m_Slider_CStick[m_Page]->GetValue();
break;
case IDS_TRIGGER_PRESS:
GCMapping[m_Page].Pressure.Shoulder = m_Slider_Trigger[m_Page]->GetValue();
break;
}
UpdateGUI();
}
void GCPadConfigDialog::UpdateGUI()
{
if(!m_ControlsCreated)
return;
// Disable all pad items if no pads are detected
bool PadEnabled = NumGoodPads != 0;
m_Joyname[m_Page]->Enable(PadEnabled);
m_ComboDeadZoneLeft[m_Page]->Enable(PadEnabled);
m_ComboDeadZoneRight[m_Page]->Enable(PadEnabled);
m_CheckS2C[m_Page]->Enable(PadEnabled);
m_ComboDiagonal[m_Page]->Enable(PadEnabled);
m_CheckRumble[m_Page]->Enable(PadEnabled);
m_RumbleStrength[m_Page]->Enable(PadEnabled);
m_TriggerType[m_Page]->Enable(PadEnabled);
for(int i = 0; i <= IDB_TRIGGER_R - IDB_ANALOG_LEFT_X; i++)
m_Button_Analog[i][m_Page]->Enable(PadEnabled);
wxString tmp;
m_Joyname[m_Page]->SetSelection(GCMapping[m_Page].ID);
m_ComboDeadZoneLeft[m_Page]->SetSelection(GCMapping[m_Page].DeadZoneL);
m_ComboDeadZoneRight[m_Page]->SetSelection(GCMapping[m_Page].DeadZoneR);
m_ComboDiagonal[m_Page]->SetSelection((100 - GCMapping[m_Page].Diagonal) / 5);
m_CheckS2C[m_Page]->SetValue(GCMapping[m_Page].bSquare2Circle);
m_CheckRumble[m_Page]->SetValue(GCMapping[m_Page].Rumble);
m_RumbleStrength[m_Page]->SetSelection(GCMapping[m_Page].RumbleStrength / 10);
m_TriggerType[m_Page]->SetSelection(GCMapping[m_Page].TriggerType);
m_Combo_StickSrc[m_Page]->SetSelection(GCMapping[m_Page].Stick.Main);
m_Combo_CStickSrc[m_Page]->SetSelection(GCMapping[m_Page].Stick.Sub);
m_Combo_TriggerSrc[m_Page]->SetSelection(GCMapping[m_Page].Stick.Shoulder);
m_Slider_Stick[m_Page]->SetValue(GCMapping[m_Page].Pressure.Main);
m_Slider_CStick[m_Page]->SetValue(GCMapping[m_Page].Pressure.Sub);
m_Slider_Trigger[m_Page]->SetValue(GCMapping[m_Page].Pressure.Shoulder);
for (int i = 0; i <= IDB_TRIGGER_R - IDB_ANALOG_LEFT_X; i++)
{
tmp << GCMapping[m_Page].AxisMapping.Code[i];
m_Button_Analog[i][m_Page]->SetLabel(tmp);
tmp.clear();
}
#ifdef _WIN32
for (int x = 0; x <= IDB_SHDR_SEMI_R - IDB_BTN_A; x++)
{
m_Button_GC[x][m_Page]->SetLabel(wxString::FromAscii(
InputCommon::VKToString(GCMapping[m_Page].Button[x + EGC_A]).c_str()));
}
#elif defined(HAVE_X11) && HAVE_X11
char keyStr[10] = {0};
for (int x = 0; x <= IDB_SHDR_SEMI_R - IDB_BTN_A; x++)
{
InputCommon::XKeyToString(GCMapping[m_Page].Button[x + EGC_A], keyStr);
m_Button_GC[x][m_Page]->SetLabel(wxString::FromAscii(keyStr));
}
#endif
DoChangeDeadZone();
}
void GCPadConfigDialog::CreateGUIControls()
{
// Search for devices and add them to the device list
wxArrayString StrJoyname; // The string array
if (NumGoodPads > 0)
{
for (int i = 0; i < NumPads; i++)
StrJoyname.Add(wxString::FromAscii(joyinfo[i].Name.c_str()));
}
else
{
StrJoyname.Add(wxT("<No Gamepad Detected>"));
}
wxArrayString TextDeadZone;
for (int i = 0; i <= 50; i++)
TextDeadZone.Add(wxString::Format(wxT("%i%%"), i));
wxArrayString StrDiagonal;
for (int i = 0; i <= 10; i++)
StrDiagonal.Add(wxString::Format(wxT("%i%%"), 100 - i * 5));
wxArrayString StrRumble;
for (int i = 0; i <= 10; i++)
StrRumble.Add(wxString::Format(wxT("%i%%"), i * 10));
wxArrayString StrSource;
StrSource.Add(wxT("Keyboard"));
StrSource.Add(wxT("Analog 1"));
StrSource.Add(wxT("Analog 2"));
StrSource.Add(wxT("Triggers"));
// The Trigger type list
wxArrayString StrTriggerType;
StrTriggerType.Add(wxT("SDL")); // -0x8000 to 0x7fff
StrTriggerType.Add(wxT("XInput")); // 0x00 to 0xff
static const wxChar* anText[] =
{
wxT("Left X-Axis"),
wxT("Left Y-Axis"),
wxT("Right X-Axis"),
wxT("Right Y-Axis"),
wxT("Left Trigger"),
wxT("Right Trigger"),
};
static const wxChar* padText[] =
{
wxT("A"),
wxT("B"),
wxT("X"),
wxT("Y"),
wxT("Z"),
wxT("Start"),
wxT("Up"), // D-Pad
wxT("Down"),
wxT("Left"),
wxT("Right"),
wxT("Up"), // Main Stick
wxT("Down"),
wxT("Left"),
wxT("Right"),
wxT("Semi"),
wxT("Up"), // C-Stick
wxT("Down"),
wxT("Left"),
wxT("Right"),
wxT("Semi"),
wxT("L"), // Triggers
wxT("R"),
wxT("Semi-L"),
wxT("Semi-R"),
};
// Configuration controls sizes
static const int BtW = 70, BtH = 20;
// A small type font
wxFont m_SmallFont(7, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
for (int i = 0; i < 4; i++)
{
m_Controller[i] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1 + i, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[i], wxString::Format(wxT("Gamecube Pad %d"), i+1));
// Controller
m_Joyname[i] = new wxChoice(m_Controller[i], IDC_JOYNAME, wxDefaultPosition, wxSize(400, -1), StrJoyname, 0, wxDefaultValidator, StrJoyname[0]);
// Dead zone
m_ComboDeadZoneLabel[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Dead Zone"));
m_ComboDeadZoneLeft[i] = new wxChoice(m_Controller[i], IDC_DEAD_ZONE_LEFT, wxDefaultPosition, wxSize(50, -1), TextDeadZone, 0, wxDefaultValidator, TextDeadZone[0]);
m_ComboDeadZoneRight[i] = new wxChoice(m_Controller[i], IDC_DEAD_ZONE_RIGHT, wxDefaultPosition, wxSize(50, -1), TextDeadZone, 0, wxDefaultValidator, TextDeadZone[0]);
// Circle to square
m_CheckS2C[i] = new wxCheckBox(m_Controller[i], IDC_STICK_S2C, wxT("Square To Circle"));
m_CheckS2C[i]->SetToolTip(wxT("This will convert a square stick radius to a circle stick radius, which is\n")
wxT("similar to the octagonal area that the original GameCube pad produces."));
// The drop down menu for the circle to square adjustment
m_DiagonalLabel[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Diagonal"));
m_DiagonalLabel[i]->SetToolTip(wxT("To produce a perfect circle in the 'Out' window you have to manually set\n")
wxT("your diagonal values here from what is shown in the 'In' window."));
m_ComboDiagonal[i] = new wxChoice(m_Controller[i], IDC_STICK_DIAGONAL, wxDefaultPosition, wxSize(50, -1), StrDiagonal, 0, wxDefaultValidator, StrDiagonal[0]);
// Rumble
m_CheckRumble[i] = new wxCheckBox(m_Controller[i], IDC_RUMBLE, wxT("Rumble"));
m_RumbleStrengthLabel[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Strength"));
m_RumbleStrength[i] = new wxChoice(m_Controller[i], IDC_RUMBLE_STRENGTH, wxDefaultPosition, wxSize(50, -1), StrRumble, 0, wxDefaultValidator, StrRumble[0]);
// Sizers
m_sDeadZoneHoriz[i] = new wxBoxSizer(wxHORIZONTAL);
m_sDeadZoneHoriz[i]->Add(m_ComboDeadZoneLeft[i], 0, (wxUP), 0);
m_sDeadZoneHoriz[i]->Add(m_ComboDeadZoneRight[i], 0, (wxUP), 0);
m_sDeadZone[i] = new wxBoxSizer(wxVERTICAL);
m_sDeadZone[i]->Add(m_ComboDeadZoneLabel[i], 0, wxALIGN_CENTER | (wxUP), 0);
m_sDeadZone[i]->Add(m_sDeadZoneHoriz[i], 0, wxALIGN_CENTER | (wxUP), 2);
m_sDiagonal[i] = new wxBoxSizer(wxHORIZONTAL);
m_sDiagonal[i]->Add(m_DiagonalLabel[i], 0, (wxUP), 4);
m_sDiagonal[i]->Add(m_ComboDiagonal[i], 0, (wxLEFT), 2);
m_sSquare2Circle[i] = new wxBoxSizer(wxVERTICAL);
m_sSquare2Circle[i]->Add(m_CheckS2C[i], 0, wxALIGN_CENTER | (wxUP), 0);
m_sSquare2Circle[i]->Add(m_sDiagonal[i], 0, wxALIGN_CENTER | (wxUP), 2);
m_sRumbleStrength[i] = new wxBoxSizer(wxHORIZONTAL);
m_sRumbleStrength[i]->Add(m_RumbleStrengthLabel[i], 0, (wxUP), 4);
m_sRumbleStrength[i]->Add(m_RumbleStrength[i], 0, (wxLEFT), 2);
m_sRumble[i] = new wxBoxSizer(wxVERTICAL);
m_sRumble[i]->Add(m_CheckRumble[i], 0, wxALIGN_CENTER | (wxUP), 0);
m_sRumble[i]->Add(m_sRumbleStrength[i], 0, wxALIGN_CENTER | (wxUP), 2);
m_sS2CDeadZone[i] = new wxBoxSizer(wxHORIZONTAL);
m_sS2CDeadZone[i]->Add(m_sDeadZone[i], 0, (wxUP), 0);
m_sS2CDeadZone[i]->Add(m_sSquare2Circle[i], 0, (wxLEFT), 40);
m_sS2CDeadZone[i]->Add(m_sRumble[i], 0, (wxLEFT), 40);
m_gJoyPad[i] = new wxStaticBoxSizer (wxVERTICAL, m_Controller[i], wxT("Gamepad"));
m_gJoyPad[i]->AddStretchSpacer();
m_gJoyPad[i]->Add(m_Joyname[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
m_gJoyPad[i]->Add(m_sS2CDeadZone[i], 0, wxALIGN_CENTER | (wxUP | wxDOWN), 4);
m_gJoyPad[i]->AddStretchSpacer();
// Row 1 Sizers: Connected pads, tilt
m_sHorizJoypad[i] = new wxBoxSizer(wxHORIZONTAL);
m_sHorizJoypad[i]->Add(m_gJoyPad[i], 0, wxEXPAND | (wxLEFT), 5);
// Stick Status Panels
m_tStatusLeftIn[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Not connected"));
m_tStatusLeftOut[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Not connected"));
m_tStatusRightIn[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Not connected"));
m_tStatusRightOut[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Not connected"));
m_pLeftInStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_bmpSquareLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize);
m_bmpDeadZoneLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus[i], wxID_ANY, CreateBitmapDeadZone(0), wxDefaultPosition, wxDefaultSize);
m_bmpDotLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize);
m_pLeftOutStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_bmpSquareLeftOut[i] = new wxStaticBitmap(m_pLeftOutStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize);
m_bmpDotLeftOut[i] = new wxStaticBitmap(m_pLeftOutStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize);
m_pRightInStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_bmpSquareRightIn[i] = new wxStaticBitmap(m_pRightInStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize);
m_bmpDeadZoneRightIn[i] = new wxStaticBitmap(m_pRightInStatus[i], wxID_ANY, CreateBitmapDeadZone(0), wxDefaultPosition, wxDefaultSize);
m_bmpDotRightIn[i] = new wxStaticBitmap(m_pRightInStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize);
m_pRightOutStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_bmpSquareRightOut[i] = new wxStaticBitmap(m_pRightOutStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize);
m_bmpDotRightOut[i] = new wxStaticBitmap(m_pRightOutStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize);
// Sizers
m_sGridStickLeft[i] = new wxGridBagSizer(0, 0);
m_sGridStickLeft[i]->Add(m_pLeftInStatus[i], wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0);
m_sGridStickLeft[i]->Add(m_pLeftOutStatus[i], wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 10);
m_sGridStickLeft[i]->Add(m_tStatusLeftIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0);
m_sGridStickLeft[i]->Add(m_tStatusLeftOut[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxLEFT, 10);
m_sGridStickRight[i] = new wxGridBagSizer(0, 0);
m_sGridStickRight[i]->Add(m_pRightInStatus[i], wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0);
m_sGridStickRight[i]->Add(m_pRightOutStatus[i], wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 10);
m_sGridStickRight[i]->Add(m_tStatusRightIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0);
m_sGridStickRight[i]->Add(m_tStatusRightOut[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxLEFT, 10);
m_gStickLeft[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog 1 Status (In) (Out)"));
m_gStickLeft[i]->Add(m_sGridStickLeft[i], 0, (wxLEFT | wxRIGHT), 5);
m_gStickRight[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog 2 Status (In) (Out)"));
m_gStickRight[i]->Add(m_sGridStickRight[i], 0, (wxLEFT | wxRIGHT), 5);
// Trigger Status Panels
m_TriggerL[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Left: "));
m_TriggerR[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Right: "));
m_TriggerStatusL[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("000"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
m_TriggerStatusR[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("000"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
m_tTriggerSource[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Trigger Source"));
m_TriggerType[i] = new wxChoice(m_Controller[i], IDC_TRIGGER_TYPE, wxDefaultPosition, wxSize(70, -1), StrTriggerType, 0, wxDefaultValidator, StrTriggerType[0]);
// Sizers
m_sGridTrigger[i] = new wxGridBagSizer(0, 0);
m_sGridTrigger[i]->Add(m_TriggerL[i], wxGBPosition(0, 0), wxGBSpan(1, 1), (wxTOP), 4);
m_sGridTrigger[i]->Add(m_TriggerStatusL[i], wxGBPosition(0, 1), wxGBSpan(1, 1), (wxLEFT | wxTOP), 4);
m_sGridTrigger[i]->Add(m_TriggerR[i], wxGBPosition(1, 0), wxGBSpan(1, 1), (wxTOP), 4);
m_sGridTrigger[i]->Add(m_TriggerStatusR[i], wxGBPosition(1, 1), wxGBSpan(1, 1), (wxLEFT | wxTOP), 4);
m_gTriggers[i] = new wxStaticBoxSizer (wxVERTICAL, m_Controller[i], wxT("Triggers Status"));
m_gTriggers[i]->AddStretchSpacer();
m_gTriggers[i]->Add(m_sGridTrigger[i], 0, wxEXPAND | (wxLEFT | wxRIGHT), 5);
m_gTriggers[i]->Add(m_tTriggerSource[i], 0, wxEXPAND | (wxUP | wxLEFT | wxRIGHT), 5);
m_gTriggers[i]->Add(m_TriggerType[i], 0, wxEXPAND | (wxUP | wxLEFT | wxRIGHT), 5);
m_gTriggers[i]->AddStretchSpacer();
// Row 2 Sizers: Analog status
m_sHorizStatus[i] = new wxBoxSizer(wxHORIZONTAL);
m_sHorizStatus[i]->Add(m_gStickLeft[i], 0, wxEXPAND | (wxLEFT), 5);
m_sHorizStatus[i]->Add(m_gStickRight[i], 0, wxEXPAND | (wxLEFT), 5);
m_sHorizStatus[i]->Add(m_gTriggers[i], 0, wxEXPAND | (wxLEFT), 5);
// Analog Axes and Triggers Mapping
m_sAnalogLeft[i] = new wxBoxSizer(wxVERTICAL);
m_sAnalogMiddle[i] = new wxBoxSizer(wxVERTICAL);
m_sAnalogRight[i] = new wxBoxSizer(wxVERTICAL);
for (int x = 0; x < 6; x++)
{
m_Text_Analog[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, anText[x]);
m_Button_Analog[x][i] = new wxButton(m_Controller[i], x + IDB_ANALOG_LEFT_X, wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH));
m_Button_Analog[x][i]->SetFont(m_SmallFont);
m_Sizer_Analog[x][i] = new wxBoxSizer(wxHORIZONTAL);
m_Sizer_Analog[x][i]->Add(m_Text_Analog[x][i], 0, (wxUP), 4);
m_Sizer_Analog[x][i]->Add(m_Button_Analog[x][i], 0, (wxLEFT), 2);
if (x < 2) // Make some balance
m_sAnalogLeft[i]->Add(m_Sizer_Analog[x][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
else if (x < 4)
m_sAnalogMiddle[i]->Add(m_Sizer_Analog[x][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
else
m_sAnalogRight[i]->Add(m_Sizer_Analog[x][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
}
m_gAnalog[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog Axes and Triggers"));
m_gAnalog[i]->Add(m_sAnalogLeft[i], 0, wxALIGN_RIGHT | (wxALL), 0);
m_gAnalog[i]->Add(m_sAnalogMiddle[i], 0, wxALIGN_RIGHT | (wxLEFT), 5);
m_gAnalog[i]->Add(m_sAnalogRight[i], 0, wxALIGN_RIGHT | (wxLEFT), 5);
// Row 3 Sizes: Analog Mapping
m_sHorizAnalog[i] = new wxBoxSizer(wxHORIZONTAL);
m_sHorizAnalog[i]->Add(m_gAnalog[i], 0, (wxLEFT), 5);
// Pad Mapping
m_gButton[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Buttons"));
m_gDPad[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("D-Pad"));
m_gStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Main Stick"));
m_Text_StickSrc[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Source"));
m_Combo_StickSrc[i] = new wxChoice(m_Controller[i], IDC_STICK_SOURCE, wxDefaultPosition, wxSize(70, -1), StrSource, 0, wxDefaultValidator, StrSource[0]);
m_sStickSrc[i] = new wxBoxSizer(wxHORIZONTAL);
m_sStickSrc[i]->Add(m_Text_StickSrc[i], 0, (wxUP), 4);
m_sStickSrc[i]->Add(m_Combo_StickSrc[i], 0, (wxLEFT), 2);
m_gStick[i]->Add(m_sStickSrc[i], 0, wxALIGN_RIGHT | (wxALL), 2);
m_gStick[i]->AddSpacer(2);
m_gCStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("C-Stick"));
m_Text_CStickSrc[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Source"));
m_Combo_CStickSrc[i] = new wxChoice(m_Controller[i], IDC_CSTICK_SOURCE, wxDefaultPosition, wxSize(70, -1), StrSource, 0, wxDefaultValidator, StrSource[0]);
m_sCStickSrc[i] = new wxBoxSizer(wxHORIZONTAL);
m_sCStickSrc[i]->Add(m_Text_CStickSrc[i], 0, (wxUP), 4);
m_sCStickSrc[i]->Add(m_Combo_CStickSrc[i], 0, (wxLEFT), 2);
m_gCStick[i]->Add(m_sCStickSrc[i], 0, wxALIGN_RIGHT | (wxALL), 2);
m_gCStick[i]->AddSpacer(2);
m_gTrigger[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Triggers"));
m_Text_TriggerSrc[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Source"));
m_Combo_TriggerSrc[i] = new wxChoice(m_Controller[i], IDC_TRIGGER_SOURCE, wxDefaultPosition, wxSize(70, -1), StrSource, 0, wxDefaultValidator, StrSource[0]);
m_sTriggerSrc[i] = new wxBoxSizer(wxHORIZONTAL);
m_sTriggerSrc[i]->Add(m_Text_TriggerSrc[i], 0, (wxUP), 4);
m_sTriggerSrc[i]->Add(m_Combo_TriggerSrc[i], 0, (wxLEFT), 2);
m_gTrigger[i]->Add(m_sTriggerSrc[i], 0, wxALIGN_RIGHT | (wxALL), 2);
m_gTrigger[i]->AddSpacer(2);
for (int x = 0; x <= IDB_SHDR_SEMI_R - IDB_BTN_A; x++)
{
m_Text_Pad[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, padText[x]);
m_Button_GC[x][i] = new wxButton(m_Controller[i], x + IDB_BTN_A, wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH));
m_Button_GC[x][i]->SetFont(m_SmallFont);
m_Sizer_Pad[x][i] = new wxBoxSizer(wxHORIZONTAL);
m_Sizer_Pad[x][i]->Add(m_Text_Pad[x][i], 0, (wxUP), 4);
m_Sizer_Pad[x][i]->Add(m_Button_GC[x][i], 0, (wxLEFT), 2);
if (x <= IDB_BTN_START)
m_gButton[i]->Add(m_Sizer_Pad[x - IDB_BTN_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
else if (x <= IDB_DPAD_RIGHT)
m_gDPad[i]->Add(m_Sizer_Pad[x - IDB_BTN_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
else if (x <= IDB_MAIN_SEMI)
m_gStick[i]->Add(m_Sizer_Pad[x - IDB_BTN_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
else if (x <= IDB_SUB_SEMI)
m_gCStick[i]->Add(m_Sizer_Pad[x - IDB_BTN_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
else
m_gTrigger[i]->Add(m_Sizer_Pad[x - IDB_BTN_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
}
m_Slider_Stick[i] = new wxSlider(m_Controller[i], IDS_STICK_PRESS, DEF_STICK_HALF, 0, DEF_STICK_FULL, wxDefaultPosition, wxSize(100,-1), wxSL_LABELS | wxSL_TOP);
m_gStick[i]->Add(m_Slider_Stick[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
m_Slider_CStick[i] = new wxSlider(m_Controller[i], IDS_CSTICK_PRESS, DEF_STICK_HALF, 0, DEF_STICK_FULL, wxDefaultPosition, wxSize(100,-1), wxSL_LABELS | wxSL_TOP);
m_gCStick[i]->Add(m_Slider_CStick[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
m_Slider_Trigger[i] = new wxSlider(m_Controller[i], IDS_TRIGGER_PRESS, DEF_TRIGGER_HALF, 0, DEF_TRIGGER_FULL, wxDefaultPosition, wxSize(100,-1), wxSL_LABELS | wxSL_TOP);
m_gTrigger[i]->Add(m_Slider_Trigger[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1);
// Row 4 Sizers: Button Mapping
m_sHorizMapping[i] = new wxBoxSizer(wxHORIZONTAL);
m_sHorizMapping[i]->Add(m_gButton[i], 0, (wxLEFT), 5);
m_sHorizMapping[i]->Add(m_gDPad[i], 0, (wxLEFT), 5);
m_sHorizMapping[i]->Add(m_gStick[i], 0, (wxLEFT), 5);
m_sHorizMapping[i]->Add(m_gCStick[i], 0, (wxLEFT), 5);
m_sHorizMapping[i]->Add(m_gTrigger[i], 0, (wxLEFT), 5);
// Set up sizers and layout
// The sizer m_sMain will be expanded inside m_Controller
m_sMain[i] = new wxBoxSizer(wxVERTICAL);
m_sMain[i]->Add(m_sHorizJoypad[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
m_sMain[i]->Add(m_sHorizStatus[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
m_sMain[i]->Add(m_sHorizAnalog[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
m_sMain[i]->Add(m_sHorizMapping[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
// Set the main sizer
m_Controller[i]->SetSizer(m_sMain[i]);
}
m_OK = new wxButton(this, wxID_OK, wxT("OK"));
m_OK->SetToolTip(wxT("Save changes and close"));
m_Cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel"));
m_Cancel->SetToolTip(wxT("Discard changes and close"));
wxBoxSizer* m_DlgButton = new wxBoxSizer(wxHORIZONTAL);
m_DlgButton->AddStretchSpacer();
m_DlgButton->Add(m_OK, 0, (wxLEFT), 5);
m_DlgButton->Add(m_Cancel, 0, (wxLEFT), 5);
m_MainSizer = new wxBoxSizer(wxVERTICAL);
m_MainSizer->Add(m_Notebook, 1, wxEXPAND | wxALL, 5);
m_MainSizer->Add(m_DlgButton, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
SetSizer(m_MainSizer);
Layout();
Fit();
// Center the window if there is room for it
#ifdef _WIN32
if (GetSystemMetrics(SM_CYFULLSCREEN) > 600)
Center();
#endif
m_ControlsCreated = true;
}
// Bitmap box and dot
wxBitmap GCPadConfigDialog::CreateBitmap()
{
BoxW = 70, BoxH = 70;
wxBitmap bitmap(BoxW, BoxH);
wxMemoryDC dc;
dc.SelectObject(bitmap);
// Set outline and fill colors
wxPen LightBluePen(_T("#7f9db9")); // Windows XP color
dc.SetPen(LightBluePen);
dc.SetBrush(*wxWHITE_BRUSH);
dc.Clear();
dc.DrawRectangle(0, 0, BoxW, BoxH);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
wxBitmap GCPadConfigDialog::CreateBitmapDot()
{
int w = 2, h = 2;
wxBitmap bitmap(w, h);
wxMemoryDC dc;
dc.SelectObject(bitmap);
// Set outline and fill colors
dc.SetPen(*wxRED_PEN);
dc.SetBrush(*wxRED_BRUSH);
dc.Clear();
dc.DrawRectangle(0, 0, w, h);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
wxBitmap GCPadConfigDialog::CreateBitmapDeadZone(int Radius)
{
wxBitmap bitmap(Radius*2, Radius*2);
wxMemoryDC dc;
dc.SelectObject(bitmap);
// Set outline and fill colors
dc.SetPen(*wxLIGHT_GREY_PEN);
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
//dc.SetBackground(*wxGREEN_BRUSH);
dc.Clear();
dc.DrawCircle(Radius, Radius, Radius);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
wxBitmap GCPadConfigDialog::CreateBitmapClear()
{
wxBitmap bitmap(BoxW, BoxH);
wxMemoryDC dc;
dc.SelectObject(bitmap);
dc.Clear();
dc.SelectObject(wxNullBitmap);
return bitmap;
}

View File

@ -0,0 +1,243 @@
// Project description
// -------------------
// Name: nJoy
// Description: A Dolphin Compatible Input Plugin
//
// Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project.
//
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef __GCPAD_CONFIGBOX_h__
#define __GCPAD_CONFIGBOX_h__
#include <wx/wx.h>
#include <wx/textctrl.h>
#include <wx/button.h>
#include <wx/stattext.h>
#include <wx/combobox.h>
#include <wx/checkbox.h>
#include <wx/notebook.h>
#include <wx/panel.h>
#include <wx/gbsizer.h>
#include "GCPad.h"
class GCPadConfigDialog : public wxDialog
{
public:
GCPadConfigDialog(wxWindow *parent, wxWindowID id = wxID_ANY,
const wxString &title = wxT("Gamecube Pad Plugin Configuration"),
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_DIALOG_STYLE);
virtual ~GCPadConfigDialog();
private:
DECLARE_EVENT_TABLE();
enum
{
// it's important that they are kept in this order
IDB_BTN_A = 0,
IDB_BTN_B,
IDB_BTN_X,
IDB_BTN_Y,
IDB_BTN_Z,
IDB_BTN_START,
IDB_DPAD_UP,
IDB_DPAD_DOWN,
IDB_DPAD_LEFT,
IDB_DPAD_RIGHT,
IDB_MAIN_UP,
IDB_MAIN_DOWN,
IDB_MAIN_LEFT,
IDB_MAIN_RIGHT,
IDB_MAIN_SEMI,
IDB_SUB_UP,
IDB_SUB_DOWN,
IDB_SUB_LEFT,
IDB_SUB_RIGHT,
IDB_SUB_SEMI,
IDB_SHDR_L,
IDB_SHDR_R,
IDB_SHDR_SEMI_L,
IDB_SHDR_SEMI_R,
// Joypad
IDB_ANALOG_LEFT_X, IDB_ANALOG_LEFT_Y,
IDB_ANALOG_RIGHT_X, IDB_ANALOG_RIGHT_Y,
IDB_TRIGGER_L, IDB_TRIGGER_R,
// Dialog controls
ID_NOTEBOOK = 1000,
ID_CONTROLLERPAGE1,
ID_CONTROLLERPAGE2,
ID_CONTROLLERPAGE3,
ID_CONTROLLERPAGE4,
// Timers
IDTM_BUTTON, IDTM_UPDATE_PAD,
// Gamepad settings
IDC_JOYNAME,
IDC_DEAD_ZONE_LEFT, IDC_DEAD_ZONE_RIGHT,
IDC_STICK_DIAGONAL, IDC_STICK_S2C,
IDC_RUMBLE, IDC_RUMBLE_STRENGTH,
IDC_TRIGGER_TYPE,
IDC_STICK_SOURCE, IDC_CSTICK_SOURCE, IDC_TRIGGER_SOURCE,
IDS_STICK_PRESS, IDS_CSTICK_PRESS, IDS_TRIGGER_PRESS,
};
wxNotebook *m_Notebook;
wxPanel *m_Controller[4],
*m_pLeftInStatus[4],
*m_pLeftOutStatus[4],
*m_pRightInStatus[4],
*m_pRightOutStatus[4];
wxStaticBitmap *m_bmpSquareLeftIn[4],
*m_bmpSquareLeftOut[4],
*m_bmpSquareRightIn[4],
*m_bmpSquareRightOut[4];
wxSlider *m_Slider_Stick[4],
*m_Slider_CStick[4],
*m_Slider_Trigger[4];
wxCheckBox *m_CheckS2C[4],
*m_CheckRumble[4];
wxButton *m_OK, *m_Cancel, *ClickedButton,
*m_Button_Analog[IDB_TRIGGER_R - IDB_ANALOG_LEFT_X + 1][4],
*m_Button_GC[IDB_SHDR_SEMI_R - IDB_BTN_A + 1][4];
wxChoice *m_Joyname[4],
*m_ComboDeadZoneLeft[4],
*m_ComboDeadZoneRight[4],
*m_ComboDiagonal[4],
*m_RumbleStrength[4],
*m_TriggerType[4],
*m_Combo_StickSrc[4],
*m_Combo_CStickSrc[4],
*m_Combo_TriggerSrc[4];
wxGridBagSizer *m_sGridStickLeft[4],
*m_sGridStickRight[4],
*m_sGridTrigger[4];
wxBoxSizer *m_MainSizer,
*m_sMain[4],
*m_sDeadZoneHoriz[4],
*m_sDeadZone[4],
*m_sDiagonal[4],
*m_sSquare2Circle[4],
*m_sS2CDeadZone[4],
*m_sRumbleStrength[4],
*m_sRumble[4],
*m_sHorizJoypad[4],
*m_sHorizStatus[4],
*m_Sizer_Analog[IDB_TRIGGER_R - IDB_ANALOG_LEFT_X + 1][4],
*m_sAnalogLeft[4],
*m_sAnalogMiddle[4],
*m_sAnalogRight[4],
*m_sHorizAnalog[4],
*m_sStickSrc[4],
*m_sCStickSrc[4],
*m_sTriggerSrc[4],
*m_Sizer_Pad[IDB_SHDR_SEMI_R - IDB_BTN_A + 1][4],
*m_sHorizMapping[4];
wxStaticBoxSizer *m_gJoyPad[4],
*m_gStickLeft[4],
*m_gStickRight[4],
*m_gTriggers[4],
*m_gAnalog[4],
*m_gButton[4],
*m_gDPad[4],
*m_gStick[4],
*m_gCStick[4],
*m_gTrigger[4];
wxStaticText *m_ComboDeadZoneLabel[4],
*m_DiagonalLabel[4],
*m_RumbleStrengthLabel[4],
*m_tStatusLeftIn[4], *m_tStatusLeftOut[4],
*m_tStatusRightIn[4], *m_tStatusRightOut[4],
*m_TriggerL[4], *m_TriggerR[4],
*m_TriggerStatusL[4], *m_TriggerStatusR[4],
*m_tTriggerSource[4],
*m_Text_Analog[IDB_TRIGGER_R - IDB_ANALOG_LEFT_X + 1][4],
*m_Text_Pad[IDB_SHDR_SEMI_R - IDB_BTN_A + 1][4],
*m_Text_StickSrc[4],
*m_Text_CStickSrc[4],
*m_Text_TriggerSrc[4];
wxStaticBitmap *m_bmpDotLeftIn[4],
*m_bmpDotLeftOut[4],
*m_bmpDotRightIn[4],
*m_bmpDotRightOut[4],
*m_bmpDeadZoneLeftIn[4],
*m_bmpDeadZoneRightIn[4];
bool m_ControlsCreated;
int m_Page, BoxW, BoxH;
int GetButtonWaitingID, GetButtonWaitingTimer, g_Pressed;
wxString OldLabel;
#if wxUSE_TIMER
wxTimer *m_UpdatePadTimer, *m_ButtonMappingTimer;
void UpdatePadInfo(wxTimerEvent& WXUNUSED(event));
void OnButtonTimer(wxTimerEvent& WXUNUSED(event)) { DoGetButtons(GetButtonWaitingID); }
#endif
wxBitmap CreateBitmap();
wxBitmap CreateBitmapDot();
wxBitmap CreateBitmapDeadZone(int Radius);
wxBitmap CreateBitmapClear();
void NotebookPageChanged(wxNotebookEvent& event);
void OnClose(wxCloseEvent& event);
void OnCloseClick(wxCommandEvent& event);
void OnKeyDown(wxKeyEvent& event);
void OnButtonClick(wxCommandEvent& event);
void OnAxisClick(wxCommandEvent& event);
void ChangeSettings(wxCommandEvent& event);
void SaveButtonMapping(int Id, int Key);
void UpdateGUI();
void CreateGUIControls();
void Convert2Box(int &x);
void DoChangeDeadZone();
void ToBlank(bool ToBlank, int Id);
void DoGetButtons(int _GetId);
void EndGetButtons();
void SetButtonText(int id, const wxString &str);
wxString GetButtonText(int id);
};
#endif // __GCPAD_CONFIGBOX_h__

View File

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

View File

@ -0,0 +1,651 @@
// Project description
// -------------------
// Name: nJoy
// Description: A Dolphin Compatible Input Plugin
//
// Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project.
//
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "GCPad.h"
#include "Config.h"
#include "LogManager.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigBox.h"
#endif
#ifdef _WIN32
#include "XInput.h"
#endif
// Declare config window so that we can write debugging info to it from functions in this file
#if defined(HAVE_WX) && HAVE_WX
GCPadConfigDialog* m_ConfigFrame = NULL;
#endif
// Variables
// ---------
bool g_SearchDeviceDone = false;
CONTROLLER_MAPPING_GC GCMapping[4];
std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
int NumPads = 0, NumGoodPads = 0, g_ID = 0;
#ifdef _WIN32
HWND m_hWnd = NULL; // Handle to window
#endif
#if defined(HAVE_X11) && HAVE_X11
Display* GCdisplay;
#endif
SPADInitialize *g_PADInitialize = NULL;
PLUGIN_GLOBALS* globals = NULL;
// Standard crap to make wxWidgets happy
#ifdef _WIN32
HINSTANCE g_hInstance;
#if defined(HAVE_WX) && HAVE_WX
class wxDLLApp : public wxApp
{
bool OnInit()
{
return true;
}
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
#endif
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
#if defined(HAVE_WX) && HAVE_WX
wxSetInstance((HINSTANCE)hinstDLL);
wxInitialize();
#endif
}
break;
case DLL_PROCESS_DETACH:
#if defined(HAVE_WX) && HAVE_WX
wxUninitialize();
#endif
break;
}
g_hInstance = hinstDLL;
return TRUE;
}
#endif
#if defined(HAVE_WX) && HAVE_WX
wxWindow* GetParentedWxWindow(HWND Parent)
{
#ifdef _WIN32
wxSetInstance((HINSTANCE)g_hInstance);
#endif
wxWindow *win = new wxWindow();
#ifdef _WIN32
win->SetHWND((WXHWND)Parent);
win->AdoptAttributesFromHWND();
#endif
return win;
}
#endif
// Input Plugin Functions (from spec's)
// ------------------------------------
// Get properties of plugin
// ------------------------
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_PAD;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin GCPad Plugin (DebugFast)");
#else
#ifdef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin GCPad Plugin (Debug)");
#else
sprintf(_PluginInfo->Name, "Dolphin GCPad Plugin");
#endif
#endif
}
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
{
globals = _pPluginGlobals;
LogManager::SetInstance((LogManager *)globals->logManager);
}
// Call config dialog
// ------------------
void DllConfig(HWND _hParent)
{
if (!g_SearchDeviceDone)
{
g_Config.Load(); // load settings
// Init Joystick + Haptic (force feedback) subsystem on SDL 1.3
// Populate joyinfo for all attached devices
Search_Devices(joyinfo, NumPads, NumGoodPads);
g_SearchDeviceDone = true;
}
#if defined(HAVE_WX) && HAVE_WX
wxWindow *frame = GetParentedWxWindow(_hParent);
m_ConfigFrame = new GCPadConfigDialog(frame);
#ifdef _WIN32
frame->Disable();
m_ConfigFrame->ShowModal();
frame->Enable();
#else
m_ConfigFrame->ShowModal();
#endif
#ifdef _WIN32
frame->SetFocus();
frame->SetHWND(NULL);
#endif
m_ConfigFrame->Destroy();
m_ConfigFrame = NULL;
frame->Destroy();
#endif
}
void DllDebugger(HWND _hParent, bool Show)
{
}
// Init PAD (start emulation)
// --------------------------
void Initialize(void *init)
{
INFO_LOG(PAD, "Initialize: %i", SDL_WasInit(0));
g_PADInitialize = (SPADInitialize*)init;
#ifdef _WIN32
m_hWnd = (HWND)g_PADInitialize->hWnd;
#endif
#if defined(HAVE_X11) && HAVE_X11
GCdisplay = (Display*)g_PADInitialize->hWnd;
#endif
if (!g_SearchDeviceDone)
{
g_Config.Load(); // load settings
// Populate joyinfo for all attached devices
Search_Devices(joyinfo, NumPads, NumGoodPads);
g_SearchDeviceDone = true;
}
}
// Shutdown PAD (stop emulation)
// -----------------------------
void Shutdown()
{
INFO_LOG(PAD, "Shutdown: %i", SDL_WasInit(0));
Close_Devices();
// Finally close SDL
if (SDL_WasInit(0))
{
SDL_Quit();
}
// Remove the pointer to the initialize data
g_PADInitialize = NULL;
g_SearchDeviceDone = false;
}
// Save state
// --------------
void DoState(unsigned char **ptr, int mode)
{
#ifdef RERECORDING
Recording::DoState(ptr, mode);
#endif
}
void EmuStateChange(PLUGIN_EMUSTATE newState)
{
}
// Set buttons status from keyboard input. Currently this is done from wxWidgets in the main application.
// --------------
void PAD_Input(u16 _Key, u8 _UpDown)
{
}
// Set PAD status
// --------------
// Called from: SI_DeviceGCController.cpp
// Function: Gives the current pad status to the Core
void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
{
// Check if all is okay
if (_pPADStatus == NULL) return;
// Clear pad
memset(_pPADStatus, 0, sizeof(SPADStatus));
const int base = 0x80;
_pPADStatus->stickX = base;
_pPADStatus->stickY = base;
_pPADStatus->substickX = base;
_pPADStatus->substickY = base;
_pPADStatus->button |= PAD_USE_ORIGIN;
_pPADStatus->err = PAD_ERR_NONE;
// Check that Dolphin is in focus, otherwise don't update the pad status
if (!IsFocus()) return;
g_ID = _numPAD;
if (NumGoodPads && NumPads > GCMapping[_numPAD].ID)
UpdatePadState(GCMapping[_numPAD]);
if (IsKey(EGC_A))
{
_pPADStatus->button |= PAD_BUTTON_A;
_pPADStatus->analogA = DEF_BUTTON_FULL;
}
if (IsKey(EGC_B))
{
_pPADStatus->button |= PAD_BUTTON_B;
_pPADStatus->analogB = DEF_BUTTON_FULL;
}
if (IsKey(EGC_X)) _pPADStatus->button |= PAD_BUTTON_X;
if (IsKey(EGC_Y)) _pPADStatus->button |= PAD_BUTTON_Y;
if (IsKey(EGC_Z)) _pPADStatus->button |= PAD_TRIGGER_Z;
if (IsKey(EGC_START)) _pPADStatus->button |= PAD_BUTTON_START;
if (IsKey(EGC_DPAD_UP)) _pPADStatus->button |= PAD_BUTTON_UP;
if (IsKey(EGC_DPAD_DOWN)) _pPADStatus->button |= PAD_BUTTON_DOWN;
if (IsKey(EGC_DPAD_LEFT)) _pPADStatus->button |= PAD_BUTTON_LEFT;
if (IsKey(EGC_DPAD_RIGHT)) _pPADStatus->button |= PAD_BUTTON_RIGHT;
if (GCMapping[_numPAD].Stick.Main == FROM_KEYBOARD)
{
int iMagnitude = DEF_STICK_FULL;
bool bUp = false;
bool bDown = false;
bool bLeft = false;
bool bRight = false;
if (IsKey(EGC_STICK_SEMI)) iMagnitude = GCMapping[_numPAD].Pressure.Main;
if (IsKey(EGC_STICK_UP)) bUp = true;
else if (IsKey(EGC_STICK_DOWN)) bDown = true;
if (IsKey(EGC_STICK_LEFT)) bLeft = true;
else if (IsKey(EGC_STICK_RIGHT)) bRight = true;
EmulateAnalogStick(_pPADStatus->stickX, _pPADStatus->stickY, bUp, bDown, bLeft, bRight, iMagnitude);
}
else if (GCMapping[_numPAD].Stick.Main == FROM_ANALOG1)
{
_pPADStatus->stickX = GCMapping[_numPAD].AxisState.Lx;
// Y-axis is inverted
_pPADStatus->stickY = 0xFF - (u8)GCMapping[_numPAD].AxisState.Ly;
}
else if (GCMapping[_numPAD].Stick.Main == FROM_ANALOG2)
{
_pPADStatus->stickX = GCMapping[_numPAD].AxisState.Rx;
// Y-axis is inverted
_pPADStatus->stickY = 0xFF - (u8)GCMapping[_numPAD].AxisState.Ry;
}
else
{
_pPADStatus->stickX = GCMapping[_numPAD].AxisState.Tl;
_pPADStatus->stickY = GCMapping[_numPAD].AxisState.Tr;
}
if (GCMapping[_numPAD].Stick.Sub == FROM_KEYBOARD)
{
int iMagnitude = DEF_STICK_FULL;
bool bUp = false;
bool bDown = false;
bool bLeft = false;
bool bRight = false;
if (IsKey(EGC_CSTICK_SEMI)) iMagnitude = GCMapping[_numPAD].Pressure.Sub;
if (IsKey(EGC_CSTICK_UP)) bUp = true;
else if (IsKey(EGC_CSTICK_DOWN)) bDown = true;
if (IsKey(EGC_CSTICK_LEFT)) bLeft = true;
else if (IsKey(EGC_CSTICK_RIGHT)) bRight = true;
EmulateAnalogStick(_pPADStatus->substickX, _pPADStatus->substickY, bUp, bDown, bLeft, bRight, iMagnitude);
}
else if (GCMapping[_numPAD].Stick.Sub == FROM_ANALOG1)
{
_pPADStatus->substickX = GCMapping[_numPAD].AxisState.Lx;
// Y-axis is inverted
_pPADStatus->substickY = 0xFF - (u8)GCMapping[_numPAD].AxisState.Ly;
}
else if (GCMapping[_numPAD].Stick.Sub == FROM_ANALOG2)
{
_pPADStatus->substickX = GCMapping[_numPAD].AxisState.Rx;
// Y-axis is inverted
_pPADStatus->substickY = 0xFF - (u8)GCMapping[_numPAD].AxisState.Ry;
}
else
{
_pPADStatus->substickX = GCMapping[_numPAD].AxisState.Tl;
_pPADStatus->substickY = GCMapping[_numPAD].AxisState.Tr;
}
if (GCMapping[_numPAD].Stick.Shoulder == FROM_KEYBOARD)
{
if (IsKey(EGC_TGR_L))
{
_pPADStatus->triggerLeft = DEF_TRIGGER_FULL;
_pPADStatus->button |= PAD_TRIGGER_L;
}
else if (IsKey(EGC_TGR_SEMI_L))
{
_pPADStatus->triggerLeft = GCMapping[_numPAD].Pressure.Shoulder;
if (_pPADStatus->triggerLeft > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_L;
}
if (IsKey(EGC_TGR_R))
{
_pPADStatus->triggerRight = DEF_TRIGGER_FULL;
_pPADStatus->button |= PAD_TRIGGER_R;
}
else if (IsKey(EGC_TGR_SEMI_R))
{
_pPADStatus->triggerRight = GCMapping[_numPAD].Pressure.Shoulder;
if (_pPADStatus->triggerRight > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_R;
}
}
else if (GCMapping[_numPAD].Stick.Shoulder == FROM_ANALOG1)
{
_pPADStatus->triggerLeft = GCMapping[_numPAD].AxisState.Lx;
_pPADStatus->triggerRight = GCMapping[_numPAD].AxisState.Ly;
EmulateAnalogTrigger(_pPADStatus->triggerLeft, _pPADStatus->triggerRight);
if (_pPADStatus->triggerLeft > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_L;
if (_pPADStatus->triggerRight > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_R;
}
else if (GCMapping[_numPAD].Stick.Shoulder == FROM_ANALOG2)
{
_pPADStatus->triggerLeft = GCMapping[_numPAD].AxisState.Rx;
_pPADStatus->triggerRight = GCMapping[_numPAD].AxisState.Ry;
EmulateAnalogTrigger(_pPADStatus->triggerLeft, _pPADStatus->triggerRight);
if (_pPADStatus->triggerLeft > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_L;
if (_pPADStatus->triggerRight > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_R;
}
else
{
_pPADStatus->triggerLeft = GCMapping[_numPAD].AxisState.Tl;
_pPADStatus->triggerRight = GCMapping[_numPAD].AxisState.Tr;
EmulateAnalogTrigger(_pPADStatus->triggerLeft, _pPADStatus->triggerRight);
if (_pPADStatus->triggerLeft > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_L;
if (_pPADStatus->triggerRight > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_R;
}
}
//******************************************************************************
// Supporting functions
//******************************************************************************
// for same displacement should be sqrt(2)/2 (in theory)
// 3/4 = 0.75 is a little faster than sqrt(2)/2 = 0.7071...
// In SMS, 17/20 = 0.85 is perfect; in WW, 7/10 = 0.70 is closer.
#define DIAGONAL_SCALE 0.70710678
void EmulateAnalogStick(unsigned char &stickX, unsigned char &stickY, bool buttonUp, bool buttonDown, bool buttonLeft, bool buttonRight, int magnitude)
{
int mainX = 0;
int mainY = 0;
if (buttonUp)
mainY = magnitude;
else if (buttonDown)
mainY = -magnitude;
if (buttonLeft)
mainX = -magnitude;
else if (buttonRight)
mainX = magnitude;
if ((mainX == 0) || (mainY == 0))
{
stickX += mainX;
stickY += mainY;
}
else
{
stickX += mainX * DIAGONAL_SCALE;
stickY += mainY * DIAGONAL_SCALE;
}
}
void EmulateAnalogTrigger(unsigned char &trL, unsigned char &trR)
{
if (GCMapping[g_ID].TriggerType == InputCommon::CTL_TRIGGER_SDL)
{
int triggerL = abs((int)trL - 0x80) * 2;
int triggerR = abs((int)trR - 0x80) * 2;
trL = (triggerL > 0xFF) ? 0xFF : triggerL;
trR = (triggerR > 0xFF) ? 0xFF : triggerR;
}
}
void Close_Devices()
{
PAD_RumbleClose();
if (SDL_WasInit(0))
{
for (int i = 0; i < NumPads; i++)
{
if (joyinfo.at(i).joy)
{
if(SDL_JoystickOpened(i))
{
INFO_LOG(WIIMOTE, "Shut down Joypad: %i", i);
SDL_JoystickClose(joyinfo.at(i).joy);
}
}
}
}
for (int i = 0; i < 4; i++)
GCMapping[i].joy = NULL;
// Clear the physical device info
joyinfo.clear();
NumPads = 0;
NumGoodPads = 0;
}
// Search for SDL devices
// ----------------
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
{
// Close opened devices first
Close_Devices();
bool success = InputCommon::SearchDevices(_joyinfo, _NumPads, _NumGoodPads);
if (_NumGoodPads == 0)
return false;
for (int i = 0; i < 4; i++)
{
if (_NumPads > GCMapping[i].ID)
if(joyinfo.at(GCMapping[i].ID).Good)
{
GCMapping[i].joy = joyinfo.at(GCMapping[i].ID).joy;
#ifdef _WIN32
XINPUT_STATE xstate;
DWORD xresult = XInputGetState(GCMapping[i].ID, &xstate);
if (xresult == ERROR_SUCCESS)
GCMapping[i].TriggerType = InputCommon::CTL_TRIGGER_XINPUT;
#endif
}
}
return success;
}
void GetAxisState(CONTROLLER_MAPPING_GC &_GCMapping)
{
// Update the gamepad status
SDL_JoystickUpdate();
// Update axis states. It doesn't hurt much if we happen to ask for nonexisting axises here.
_GCMapping.AxisState.Lx = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Lx);
_GCMapping.AxisState.Ly = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Ly);
_GCMapping.AxisState.Rx = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Rx);
_GCMapping.AxisState.Ry = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Ry);
// Update the analog trigger axis values
#ifdef _WIN32
if (_GCMapping.TriggerType == InputCommon::CTL_TRIGGER_SDL)
{
#endif
// If we are using SDL analog triggers the buttons have to be mapped as 1000 or up, otherwise they are not used
// We must also check that we are not asking for a negative axis number because SDL_JoystickGetAxis() has
// no good way of handling that
if ((_GCMapping.AxisMapping.Tl - 1000) >= 0)
_GCMapping.AxisState.Tl = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Tl - 1000);
if ((_GCMapping.AxisMapping.Tr - 1000) >= 0)
_GCMapping.AxisState.Tr = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Tr - 1000);
#ifdef _WIN32
}
else
{
_GCMapping.AxisState.Tl = XInput::GetXI(_GCMapping.ID, _GCMapping.AxisMapping.Tl - 1000);
_GCMapping.AxisState.Tr = XInput::GetXI(_GCMapping.ID, _GCMapping.AxisMapping.Tr - 1000);
}
#endif
}
void UpdatePadState(CONTROLLER_MAPPING_GC &_GCiMapping)
{
// Return if we have no pads
if (NumGoodPads == 0) return;
GetAxisState(_GCiMapping);
int &Lx = _GCiMapping.AxisState.Lx;
int &Ly = _GCiMapping.AxisState.Ly;
int &Rx = _GCiMapping.AxisState.Rx;
int &Ry = _GCiMapping.AxisState.Ry;
int &Tl = _GCiMapping.AxisState.Tl;
int &Tr = _GCiMapping.AxisState.Tr;
// Check the circle to square option
if(_GCiMapping.bSquare2Circle)
{
InputCommon::Square2Circle(Lx, Ly, _GCiMapping.Diagonal, false);
InputCommon::Square2Circle(Rx, Ry, _GCiMapping.Diagonal, false);
}
// Dead zone adjustment
float DeadZoneLeft = (float)_GCiMapping.DeadZoneL / 100.0f;
float DeadZoneRight = (float)_GCiMapping.DeadZoneR / 100.0f;
if (InputCommon::IsDeadZone(DeadZoneLeft, Lx, Ly))
{
Lx = 0;
Ly = 0;
}
if (InputCommon::IsDeadZone(DeadZoneRight, Rx, Ry))
{
Rx = 0;
Ry = 0;
}
// Downsize the values from 0x8000 to 0x80
Lx = InputCommon::Pad_Convert(Lx);
Ly = InputCommon::Pad_Convert(Ly);
Rx = InputCommon::Pad_Convert(Rx);
Ry = InputCommon::Pad_Convert(Ry);
// The XInput range is already 0 to 0x80
if (_GCiMapping.TriggerType == InputCommon::CTL_TRIGGER_SDL)
{
Tl = InputCommon::Pad_Convert(Tl);
Tr = InputCommon::Pad_Convert(Tr);
}
}
// Multi System Input Status Check
bool IsKey(int Key)
{
int Ret = NULL;
int MapKey = GCMapping[g_ID].Button[Key];
#ifdef _WIN32
if (MapKey < 256)
{
Ret = GetAsyncKeyState(MapKey); // Keyboard (Windows)
}
else if (MapKey < 0x1100)
#elif defined HAVE_X11 && HAVE_X11
if (MapKey < 256 || MapKey > 0xf000)
{
char keys[32];
KeyCode keyCode;
XQueryKeymap(GCdisplay, keys);
keyCode = XKeysymToKeycode(GCdisplay, MapKey);
Ret = (keys[keyCode/8] & (1 << (keyCode%8))); // Keyboard (Linux)
}
else if (MapKey < 0x1100)
#else
if (MapKey < 0x1100)
#endif
{
Ret = SDL_JoystickGetButton(GCMapping[g_ID].joy, MapKey - 0x1000); // Pad button
}
else // Pad hat
{
u8 HatCode, HatKey;
HatCode = SDL_JoystickGetHat(GCMapping[g_ID].joy, (MapKey - 0x1100) / 0x0010);
HatKey = (MapKey - 0x1100) % 0x0010;
if (HatCode & HatKey)
Ret = HatKey;
}
return (Ret) ? true : false;
}
// Check if Dolphin is in focus
// ----------------
bool IsFocus()
{
return g_PADInitialize->pRendererHasFocus();
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,532 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="Plugin_GCPadNew"
ProjectGUID="{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}"
RootNamespace="Plugin_GCPadNew"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
WarnAsError="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\$(ProjectName)D.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName)D.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
WarnAsError="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\$(ProjectName).dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName).dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugFast|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;DEBUGFAST;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
WarnAsError="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\$(ProjectName)DF.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugFast|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;DEBUGFAST;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName)DF.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\Src\GCPadEmu.cpp"
>
</File>
<File
RelativePath=".\Src\GCPadEmu.h"
>
</File>
<File
RelativePath=".\Src\GCPadNew.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,108 @@
#include "GCPadEmu.h"
const u16 button_bitmasks[] =
{
PAD_BUTTON_A,
PAD_BUTTON_B,
PAD_BUTTON_X,
PAD_BUTTON_Y,
PAD_TRIGGER_Z,
PAD_BUTTON_START
};
const u16 trigger_bitmasks[] =
{
PAD_TRIGGER_L,
PAD_TRIGGER_R,
};
const u16 dpad_bitmasks[] =
{
PAD_BUTTON_UP, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT
};
const char* const named_buttons[] =
{
"A",
"B",
"X",
"Y",
"Z",
"Start",
};
const char* const named_triggers[] =
{
"L", "R", "L-Analog", "R-Analog"
};
GCPad::GCPad( const unsigned int index ) : m_index(index)
{
// buttons
groups.push_back( m_buttons = new Buttons( "Buttons" ) );
for ( unsigned int i=0; i < sizeof(named_buttons)/sizeof(*named_buttons); ++i )
m_buttons->controls.push_back( new ControlGroup::Input( named_buttons[i] ) );
// sticks
groups.push_back( m_main_stick = new AnalogStick( "Main Stick" ) );
groups.push_back( m_c_stick = new AnalogStick( "C-Stick" ) );
// triggers
groups.push_back( m_triggers = new MixedTriggers( "Triggers" ) );
for ( unsigned int i=0; i < sizeof(named_triggers)/sizeof(*named_triggers); ++i )
m_triggers->controls.push_back( new ControlGroup::Input( named_triggers[i] ) );
// rumble
groups.push_back( m_rumble = new ControlGroup( "Rumble" ) );
m_rumble->controls.push_back( new ControlGroup::Output( "Motor" ) );
// dpad
groups.push_back( m_dpad = new Buttons( "D-Pad" ) );
for ( unsigned int i=0; i < 4; ++i )
m_dpad->controls.push_back( new ControlGroup::Input( named_directions[i] ) );
// options
groups.push_back( m_options = new ControlGroup( "Options" ) );
m_options->settings.push_back( new ControlGroup::Setting( "Background Input", false ) );
}
std::string GCPad::GetName() const
{
return std::string("GCPad") + char('1'+m_index);
}
void GCPad::GetInput( SPADStatus* const pad )
{
// if window has focus or background input enabled
if (g_PADInitialize->pRendererHasFocus() || m_options[0].settings[0]->value )
{
// buttons
m_buttons->GetState( &pad->button, button_bitmasks );
// TODO: set analog A/B analog to full or w/e, prolly not needed
// dpad
m_dpad->GetState( &pad->button, dpad_bitmasks );
// sticks
m_main_stick->GetState( &pad->stickX, &pad->stickY, 0x80, 127 );
m_c_stick->GetState( &pad->substickX, &pad->substickY, 0x80, 127 );
// triggers
m_triggers->GetState( &pad->button, trigger_bitmasks, &pad->triggerLeft, 0xFF );
}
else
{
// center sticks
memset( &pad->stickX, 0x80, 4 );
}
}
void GCPad::SetOutput( const bool on )
{
// only rumble if window has focus or background input is enabled
m_rumble->controls[0]->control_ref->State( on && (g_PADInitialize->pRendererHasFocus() || m_options[0].settings[0]->value) );
}

View File

@ -0,0 +1,34 @@
#ifndef _CONEMU_GCPAD_H_
#define _CONEMU_GCPAD_H_
#include <ControllerEmu.h>
extern SPADInitialize *g_PADInitialize;
class GCPad : public ControllerEmu
{
public:
GCPad( const unsigned int index );
void GetInput( SPADStatus* const pad );
void SetOutput( const bool on );
std::string GetName() const;
private:
Buttons* m_buttons;
AnalogStick* m_main_stick;
AnalogStick* m_c_stick;
Buttons* m_dpad;
MixedTriggers* m_triggers;
ControlGroup* m_rumble;
ControlGroup* m_options;
const unsigned int m_index;
};
#endif

View File

@ -0,0 +1,349 @@
#include "Common.h"
#include "pluginspecs_pad.h"
#include "ControllerInterface/ControllerInterface.h"
#include "GCPadEmu.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigDiag.h"
#endif
#include "../../InputPluginCommon/Src/Config.h"
#if defined(HAVE_X11) && HAVE_X11
#include <X11/Xlib.h>
#endif
#define PLUGIN_VERSION 0x0100
#define PLUGIN_NAME "Dolphin GCPad New"
#ifdef DEBUGFAST
#define PLUGIN_FULL_NAME PLUGIN_NAME" (DebugFast)"
#else
#ifdef _DEBUG
#define PLUGIN_FULL_NAME PLUGIN_NAME" (Debug)"
#else
#define PLUGIN_FULL_NAME PLUGIN_NAME
#endif
#endif
// plugin globals
static Plugin g_plugin( "GCPadNew", "Pad", "GCPad" );
SPADInitialize *g_PADInitialize = NULL;
#ifdef _WIN32
class wxDLLApp : public wxApp
{
bool OnInit()
{
return true;
};
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
#endif
// copied from GCPad
HINSTANCE g_hInstance;
// copied from GCPad
#if defined(HAVE_WX) && HAVE_WX
wxWindow* GetParentedWxWindow(HWND Parent)
{
#ifdef _WIN32
wxSetInstance((HINSTANCE)g_hInstance);
#endif
wxWindow *win = new wxWindow();
#ifdef _WIN32
win->SetHWND((WXHWND)Parent);
win->AdoptAttributesFromHWND();
#endif
return win;
}
#endif
// /
#ifdef _WIN32
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
wxSetInstance(hinstDLL);
wxInitialize();
break;
case DLL_PROCESS_DETACH:
wxUninitialize();
break;
default:
break;
}
g_hInstance = hinstDLL;
return TRUE;
}
#endif
void DeInitPlugin()
{
// i realize i am checking IsInit() twice, just too lazy to change it
if ( g_plugin.controller_interface.IsInit() )
{
std::vector<ControllerEmu*>::const_iterator
i = g_plugin.controllers.begin(),
e = g_plugin.controllers.end();
for ( ; i!=e; ++i )
delete *i;
g_plugin.controllers.clear();
g_plugin.controller_interface.DeInit();
}
}
// if plugin isn't initialized, init and load config
void InitPlugin( void* const hwnd )
{
// i realize i am checking IsInit() twice, just too lazy to change it
if ( false == g_plugin.controller_interface.IsInit() )
{
// add 4 gcpads
for ( unsigned int i = 0; i<4; ++i )
g_plugin.controllers.push_back( new GCPad( i ) );
// load the saved controller config
g_plugin.LoadConfig();
// needed for Xlib and exclusive dinput
g_plugin.controller_interface.SetHwnd( hwnd );
g_plugin.controller_interface.Init();
// update control refs
std::vector<ControllerEmu*>::const_iterator i = g_plugin.controllers.begin(),
e = g_plugin.controllers.end();
for ( ; i!=e; ++i )
(*i)->UpdateReferences( g_plugin.controller_interface );
}
}
// I N T E R F A C E
// __________________________________________________________________________________________________
// Function:
// Purpose:
// input:
// output:
//
void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
{
memset( _pPADStatus, 0, sizeof(*_pPADStatus) );
_pPADStatus->err = PAD_ERR_NONE;
// wtf is this?
_pPADStatus->button |= PAD_USE_ORIGIN;
// try lock
if ( false == g_plugin.controls_crit.TryEnter() )
{
// if gui has lock (messing with controls), skip this input cycle
// center axes and return
memset( &_pPADStatus->stickX, 0x80, 4 );
return;
}
// if we are on the next input cycle, update output and input
// if we can get a lock
static int _last_numPAD = 4;
if ( _numPAD <= _last_numPAD && g_plugin.interface_crit.TryEnter() )
{
g_plugin.controller_interface.UpdateOutput();
g_plugin.controller_interface.UpdateInput();
g_plugin.interface_crit.Leave();
}
_last_numPAD = _numPAD;
// get input
((GCPad*)g_plugin.controllers[ _numPAD ])->GetInput( _pPADStatus );
// leave
g_plugin.controls_crit.Leave();
}
// __________________________________________________________________________________________________
// Function: Send keyboard input to the plugin
// Purpose:
// input: The key and if it's pressed or released
// output: None
//
void PAD_Input(u16 _Key, u8 _UpDown)
{
// nofin
}
// __________________________________________________________________________________________________
// Function: PAD_Rumble
// Purpose: Pad rumble!
// input: PAD number, Command type (Stop=0, Rumble=1, Stop Hard=2) and strength of Rumble
// output: none
//
void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
{
// enter
if ( g_plugin.controls_crit.TryEnter() )
{
// TODO: this has potential to not stop rumble if user is messing with GUI at the perfect time
// set rumble
((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( 1 == _uType && _uStrength > 2 );
// leave
g_plugin.controls_crit.Leave();
}
}
// GLOBAL I N T E R F A C E
// Function: GetDllInfo
// Purpose: This function allows the emulator to gather information
// about the DLL by filling in the PluginInfo structure.
// input: A pointer to a PLUGIN_INFO structure that needs to be
// filled by the function. (see def above)
// output: none
//
void GetDllInfo(PLUGIN_INFO* _pPluginInfo)
{
// don't feel like messing around with all those strcpy functions and warnings
//char *s1 = CIFACE_PLUGIN_FULL_NAME, *s2 = _pPluginInfo->Name;
//while ( *s2++ = *s1++ );
memcpy( _pPluginInfo->Name, PLUGIN_FULL_NAME, sizeof(PLUGIN_FULL_NAME) );
_pPluginInfo->Type = PLUGIN_TYPE_PAD;
_pPluginInfo->Version = PLUGIN_VERSION;
}
// ___________________________________________________________________________
// Function: DllConfig
// Purpose: This function is optional function that is provided
// to allow the user to configure the DLL
// input: A handle to the window that calls this function
// output: none
//
void DllConfig(HWND _hParent)
{
bool was_init = false;
#if defined(HAVE_X11) && HAVE_X11
Display *dpy = NULL;
#endif
if ( g_plugin.controller_interface.IsInit() ) // check if game is running
was_init = true;
else
{
#if defined(HAVE_X11) && HAVE_X11
dpy = XOpenDisplay(0);
InitPlugin(dpy);
#else
InitPlugin(_hParent);
#endif
}
// copied from GCPad
#if defined(HAVE_WX) && HAVE_WX
wxWindow *frame = GetParentedWxWindow(_hParent);
ConfigDialog* m_ConfigFrame = new ConfigDialog( frame, g_plugin, PLUGIN_FULL_NAME, was_init );
#ifdef _WIN32
frame->Disable();
m_ConfigFrame->ShowModal();
frame->Enable();
#else
m_ConfigFrame->ShowModal();
#endif
#ifdef _WIN32
wxMilliSleep( 50 ); // hooray for hacks
frame->SetFocus();
frame->SetHWND(NULL);
#endif
m_ConfigFrame->Destroy();
m_ConfigFrame = NULL;
frame->Destroy();
#endif
// /
if ( !was_init ) // if game is running
{
#if defined(HAVE_X11) && HAVE_X11
XCloseDisplay(dpy);
#endif
DeInitPlugin();
}
}
// ___________________________________________________________________________
// Function: DllDebugger
// Purpose: Open the debugger
// input: a handle to the window that calls this function
// output: none
//
void DllDebugger(HWND _hParent, bool Show)
{
// wut?
}
// ___________________________________________________________________________
// Function: DllSetGlobals
// Purpose: Set the pointer for globals variables
// input: a pointer to the global struct
// output: none
//
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
{
// wut?
}
// ___________________________________________________________________________
// Function: Initialize
// Purpose: Initialize the plugin
// input: Init
// output: none
//
void Initialize(void *init)
{
g_PADInitialize = (SPADInitialize*)init;
if ( false == g_plugin.controller_interface.IsInit() )
InitPlugin( g_PADInitialize->hWnd );
}
// ___________________________________________________________________________
// Function: Shutdown
// Purpose: This function is called when the emulator is shutting down
// a game allowing the dll to de-initialise.
// input: none
// output: none
//
void Shutdown(void)
{
if ( g_plugin.controller_interface.IsInit() )
DeInitPlugin();
}
// ___________________________________________________________________________
// Function: DoState
// Purpose: Saves/load state
// input/output: ptr
// input: mode
//
void DoState(unsigned char **ptr, int mode)
{
// prolly won't need this
}
// ___________________________________________________________________________
// Function: EmuStateChange
// Purpose: Notifies the plugin of a change in emulation state
// input: newState
// output: none
//
void EmuStateChange(PLUGIN_EMUSTATE newState)
{
// maybe use this later
}

View File

@ -0,0 +1,21 @@
# -*- python -*-
Import('env')
import sys
name = "Plugin_GCPadNew"
padenv = env.Clone()
files = [
'GCPadNew.cpp',
'GCPadEmu.cpp',
]
padenv.Append(
LIBS = [ 'inputplugincommon', 'inputcommon', 'common' ],
)
if sys.platform == 'darwin':
padenv['FRAMEWORKS'] = ['CoreFoundation', 'System', 'Cocoa', 'IOKit' ]
padenv.SharedLibrary(env['plugin_dir']+name, files)

View File

@ -77,8 +77,7 @@ void GFXDebuggerDX9::SaveSettings() const
{
IniFile file;
file.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
Section& videowindow = file["VideoWindow"];
// TODO: make this work when we close the entire program too, currently on total close we get
// weird values, perhaps because of some conflict with the rendering window
// TODO: get the screen resolution and make limits from that
@ -86,13 +85,13 @@ void GFXDebuggerDX9::SaveSettings() const
&& GetSize().GetWidth() < 1000
&& GetSize().GetHeight() < 1000)
{
videowindow.Set("x", GetPosition().x);
videowindow.Set("y", GetPosition().y);
videowindow.Set("w", GetSize().GetWidth());
videowindow.Set("h", GetSize().GetHeight());
file.Set("VideoWindow", "x", GetPosition().x);
file.Set("VideoWindow", "y", GetPosition().y);
file.Set("VideoWindow", "w", GetSize().GetWidth());
file.Set("VideoWindow", "h", GetSize().GetHeight());
}
videowindow.Set("WriteToFile", m_Check[0]->IsChecked());
file.Set("VideoWindow", "WriteToFile", m_Check[0]->IsChecked());
//g_Config.iLog = bInfoLog ? CONF_LOG : 0;
//g_Config.iLog |= bPrimLog ? CONF_PRIMLOG : 0;
@ -100,7 +99,7 @@ void GFXDebuggerDX9::SaveSettings() const
//g_Config.iLog |= bSaveTargets ? CONF_SAVETARGETS : 0;
//g_Config.iLog |= bSaveShaders ? CONF_SAVESHADERS : 0;
//videowindow.Set("ConfBits", g_Config.iLog);
//file.Set("VideoWindow", "ConfBits", g_Config.iLog);
file.Save(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
}
@ -110,12 +109,11 @@ void GFXDebuggerDX9::LoadSettings()
IniFile file;
file.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
Section& videowindow = file["VideoWindow"];
int x = 100, y = 100, w = 100, h = 100;
videowindow.Get("x", &x, GetPosition().x);
videowindow.Get("y", &y, GetPosition().y);
videowindow.Get("w", &w, GetSize().GetWidth());
videowindow.Get("h", &h, GetSize().GetHeight());
file.Get("VideoWindow", "x", &x, GetPosition().x);
file.Get("VideoWindow", "y", &y, GetPosition().y);
file.Get("VideoWindow", "w", &w, GetSize().GetWidth());
file.Get("VideoWindow", "h", &h, GetSize().GetHeight());
SetSize(x, y, w, h);
//file.Get("VideoWindow", "ConfBits", &g_Config.iLog, 0);

View File

@ -68,7 +68,6 @@ void GFXDebuggerOGL::SaveSettings() const
IniFile file;
file.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
Section& vidwin = file["VideoWindow"];
// TODO: make this work when we close the entire program too, currently on total close we get
// weird values, perhaps because of some conflict with the rendering window
// TODO: get the screen resolution and make limits from that
@ -76,13 +75,13 @@ void GFXDebuggerOGL::SaveSettings() const
&& GetSize().GetWidth() < 1000
&& GetSize().GetHeight() < 1000)
{
vidwin.Set("x", GetPosition().x);
vidwin.Set("y", GetPosition().y);
vidwin.Set("w", GetSize().GetWidth());
vidwin.Set("h", GetSize().GetHeight());
file.Set("VideoWindow", "x", GetPosition().x);
file.Set("VideoWindow", "y", GetPosition().y);
file.Set("VideoWindow", "w", GetSize().GetWidth());
file.Set("VideoWindow", "h", GetSize().GetHeight());
}
vidwin.Set("WriteToFile", m_Check[0]->IsChecked());
file.Set("VideoWindow", "WriteToFile", m_Check[0]->IsChecked());
g_Config.iLog = bInfoLog ? CONF_LOG : 0;
g_Config.iLog |= bPrimLog ? CONF_PRIMLOG : 0;
@ -90,7 +89,7 @@ void GFXDebuggerOGL::SaveSettings() const
g_Config.iLog |= bSaveTargets ? CONF_SAVETARGETS : 0;
g_Config.iLog |= bSaveShaders ? CONF_SAVESHADERS : 0;
vidwin.Set("ConfBits", g_Config.iLog);
file.Set("VideoWindow", "ConfBits", g_Config.iLog);
file.Save(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
}
@ -100,15 +99,14 @@ void GFXDebuggerOGL::LoadSettings()
IniFile file;
file.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
Section& vidwin = file["VideoWindow"];
int x = 100, y = 100, w = 100, h = 100;
vidwin.Get("x", &x, GetPosition().x);
vidwin.Get("y", &y, GetPosition().y);
vidwin.Get("w", &w, GetSize().GetWidth());
vidwin.Get("h", &h, GetSize().GetHeight());
file.Get("VideoWindow", "x", &x, GetPosition().x);
file.Get("VideoWindow", "y", &y, GetPosition().y);
file.Get("VideoWindow", "w", &w, GetSize().GetWidth());
file.Get("VideoWindow", "h", &h, GetSize().GetHeight());
SetSize(x, y, w, h);
vidwin.Get("ConfBits", &g_Config.iLog, 0);
file.Get("VideoWindow", "ConfBits", &g_Config.iLog, 0);
bInfoLog = (g_Config.iLog & CONF_LOG) ? true : false;
bPrimLog = (g_Config.iLog & CONF_PRIMLOG) ? true : false;
bSaveTextures = (g_Config.iLog & CONF_SAVETEXTURES) ? true : false;

View File

@ -406,7 +406,7 @@ bool OpenGL_MakeCurrent()
#if defined(USE_WX) && USE_WX
GLWin.glCanvas->SetCurrent(*GLWin.glCtxt);
#elif defined(_WIN32)
return wglMakeCurrent(hDC,hRC) != 0;
return wglMakeCurrent(hDC,hRC);
#elif defined(HAVE_X11) && HAVE_X11
g_VideoInitialize.pRequestWindowSize(GLWin.x, GLWin.y, (int&)GLWin.width, (int&)GLWin.height);
XMoveResizeWindow(GLWin.dpy, GLWin.win, GLWin.x, GLWin.y, GLWin.width, GLWin.height);

View File

@ -45,9 +45,8 @@ void Config::Load()
IniFile iniFile;
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_software.ini").c_str());
Section& hardware = iniFile["Hardware"];
hardware.Get("Fullscreen", &bFullscreen, false); // Hardware
hardware.Get("RenderToMainframe", &renderToMainframe, false);
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
}
@ -57,9 +56,8 @@ void Config::Save()
IniFile iniFile;
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_software.ini").c_str());
Section& hardware = iniFile["Hardware"];
hardware.Set("Fullscreen", bFullscreen);
hardware.Set("RenderToMainframe", renderToMainframe);
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
iniFile.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str());
}

View File

@ -263,85 +263,82 @@ void Config::Load()
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Wiimote.ini").c_str());
// Real Wiimote
Section& real = iniFile["Real"];
real.Get("UpdateStatus", &bUpdateRealWiimote, true);
real.Get("Unpair", &bUnpairRealWiimote, false);
real.Get("Autopair", &bPairRealWiimote, false);
real.Get("Timeout", &bWiiReadTimeout, 10);
real.Get("AccNeutralX", &iAccNeutralX, 0);
real.Get("AccNeutralY", &iAccNeutralY, 0);
real.Get("AccNeutralZ", &iAccNeutralZ, 0);
real.Get("AccNunNeutralX", &iAccNunNeutralX, 0);
real.Get("AccNunNeutralY", &iAccNunNeutralY, 0);
real.Get("AccNunNeutralZ", &iAccNunNeutralZ, 0);
iniFile.Get("Real", "UpdateStatus", &bUpdateRealWiimote, true);
iniFile.Get("Real", "Unpair", &bUnpairRealWiimote, false);
iniFile.Get("Real", "Autopair", &bPairRealWiimote, false);
iniFile.Get("Real", "Timeout", &bWiiReadTimeout, 10);
iniFile.Get("Real", "AccNeutralX", &iAccNeutralX, 0);
iniFile.Get("Real", "AccNeutralY", &iAccNeutralY, 0);
iniFile.Get("Real", "AccNeutralZ", &iAccNeutralZ, 0);
iniFile.Get("Real", "AccNunNeutralX", &iAccNunNeutralX, 0);
iniFile.Get("Real", "AccNunNeutralY", &iAccNunNeutralY, 0);
iniFile.Get("Real", "AccNunNeutralZ", &iAccNunNeutralZ, 0);
for (int i = 0; i < MAX_WIIMOTES; i++)
{
// Slot specific settings
char SectionName[32];
sprintf(SectionName, "Wiimote%i", i + 1);
Section& section = iniFile[SectionName];
// General
section.Get("Source", &WiiMoteEmu::WiiMapping[i].Source, (i == 0) ? 1 : 0);
iniFile.Get(SectionName, "Source", &WiiMoteEmu::WiiMapping[i].Source, (i == 0) ? 1 : 0);
section.Get("Sideways", &WiiMoteEmu::WiiMapping[i].bSideways, false);
section.Get("Upright", &WiiMoteEmu::WiiMapping[i].bUpright, false);
section.Get("ExtensionConnected", &WiiMoteEmu::WiiMapping[i].iExtensionConnected, WiiMoteEmu::EXT_NONE);
section.Get("MotionPlusConnected", &WiiMoteEmu::WiiMapping[i].bMotionPlusConnected, false);
iniFile.Get(SectionName, "Sideways", &WiiMoteEmu::WiiMapping[i].bSideways, false);
iniFile.Get(SectionName, "Upright", &WiiMoteEmu::WiiMapping[i].bUpright, false);
iniFile.Get(SectionName, "ExtensionConnected", &WiiMoteEmu::WiiMapping[i].iExtensionConnected, WiiMoteEmu::EXT_NONE);
iniFile.Get(SectionName, "MotionPlusConnected", &WiiMoteEmu::WiiMapping[i].bMotionPlusConnected, false);
section.Get("TiltInputWM", &WiiMoteEmu::WiiMapping[i].Tilt.InputWM, WiiMoteEmu::FROM_KEYBOARD);
section.Get("TiltInputNC", &WiiMoteEmu::WiiMapping[i].Tilt.InputNC, WiiMoteEmu::FROM_KEYBOARD);
section.Get("TiltRollDegree", &WiiMoteEmu::WiiMapping[i].Tilt.RollDegree, 60);
section.Get("TiltRollSwing", &WiiMoteEmu::WiiMapping[i].Tilt.RollSwing, false);
section.Get("TiltRollInvert", &WiiMoteEmu::WiiMapping[i].Tilt.RollInvert, false);
iniFile.Get(SectionName, "TiltInputWM", &WiiMoteEmu::WiiMapping[i].Tilt.InputWM, WiiMoteEmu::FROM_KEYBOARD);
iniFile.Get(SectionName, "TiltInputNC", &WiiMoteEmu::WiiMapping[i].Tilt.InputNC, WiiMoteEmu::FROM_KEYBOARD);
iniFile.Get(SectionName, "TiltRollDegree", &WiiMoteEmu::WiiMapping[i].Tilt.RollDegree, 60);
iniFile.Get(SectionName, "TiltRollSwing", &WiiMoteEmu::WiiMapping[i].Tilt.RollSwing, false);
iniFile.Get(SectionName, "TiltRollInvert", &WiiMoteEmu::WiiMapping[i].Tilt.RollInvert, false);
WiiMoteEmu::WiiMapping[i].Tilt.RollRange = (WiiMoteEmu::WiiMapping[i].Tilt.RollSwing) ? 0 : WiiMoteEmu::WiiMapping[i].Tilt.RollDegree;
section.Get("TiltPitchDegree", &WiiMoteEmu::WiiMapping[i].Tilt.PitchDegree, 60);
section.Get("TiltPitchSwing", &WiiMoteEmu::WiiMapping[i].Tilt.PitchSwing, false);
section.Get("TiltPitchInvert", &WiiMoteEmu::WiiMapping[i].Tilt.PitchInvert, false);
iniFile.Get(SectionName, "TiltPitchDegree", &WiiMoteEmu::WiiMapping[i].Tilt.PitchDegree, 60);
iniFile.Get(SectionName, "TiltPitchSwing", &WiiMoteEmu::WiiMapping[i].Tilt.PitchSwing, false);
iniFile.Get(SectionName, "TiltPitchInvert", &WiiMoteEmu::WiiMapping[i].Tilt.PitchInvert, false);
WiiMoteEmu::WiiMapping[i].Tilt.PitchRange = (WiiMoteEmu::WiiMapping[i].Tilt.PitchSwing) ? 0 : WiiMoteEmu::WiiMapping[i].Tilt.PitchDegree;
// StickMapping
section.Get("NCStick", &WiiMoteEmu::WiiMapping[i].Stick.NC, WiiMoteEmu::FROM_KEYBOARD);
section.Get("CCStickLeft", &WiiMoteEmu::WiiMapping[i].Stick.CCL, WiiMoteEmu::FROM_KEYBOARD);
section.Get("CCStickRight", &WiiMoteEmu::WiiMapping[i].Stick.CCR, WiiMoteEmu::FROM_KEYBOARD);
section.Get("CCTriggers", &WiiMoteEmu::WiiMapping[i].Stick.CCT, WiiMoteEmu::FROM_KEYBOARD);
section.Get("GHStick", &WiiMoteEmu::WiiMapping[i].Stick.GH, WiiMoteEmu::FROM_KEYBOARD);
iniFile.Get(SectionName, "NCStick", &WiiMoteEmu::WiiMapping[i].Stick.NC, WiiMoteEmu::FROM_KEYBOARD);
iniFile.Get(SectionName, "CCStickLeft", &WiiMoteEmu::WiiMapping[i].Stick.CCL, WiiMoteEmu::FROM_KEYBOARD);
iniFile.Get(SectionName, "CCStickRight", &WiiMoteEmu::WiiMapping[i].Stick.CCR, WiiMoteEmu::FROM_KEYBOARD);
iniFile.Get(SectionName, "CCTriggers", &WiiMoteEmu::WiiMapping[i].Stick.CCT, WiiMoteEmu::FROM_KEYBOARD);
iniFile.Get(SectionName, "GHStick", &WiiMoteEmu::WiiMapping[i].Stick.GH, WiiMoteEmu::FROM_KEYBOARD);
// ButtonMapping
for (int x = 0; x < WiiMoteEmu::LAST_CONSTANT; x++)
section.Get(wmControlNames[x], &WiiMoteEmu::WiiMapping[i].Button[x], wmDefaultControls[x]);
iniFile.Get(SectionName, wmControlNames[x], &WiiMoteEmu::WiiMapping[i].Button[x], wmDefaultControls[x]);
// This pad Id could possibly be higher than the number of pads that are connected,
// but we check later, when needed, that that is not the case
section.Get("DeviceID", &WiiMoteEmu::WiiMapping[i].ID, 0);
iniFile.Get(SectionName, "DeviceID", &WiiMoteEmu::WiiMapping[i].ID, 0);
section.Get("Axis_Lx", &WiiMoteEmu::WiiMapping[i].AxisMapping.Lx, 0);
section.Get("Axis_Ly", &WiiMoteEmu::WiiMapping[i].AxisMapping.Ly, 1);
section.Get("Axis_Rx", &WiiMoteEmu::WiiMapping[i].AxisMapping.Rx, 2);
section.Get("Axis_Ry", &WiiMoteEmu::WiiMapping[i].AxisMapping.Ry, 3);
section.Get("Trigger_L", &WiiMoteEmu::WiiMapping[i].AxisMapping.Tl, 1004);
section.Get("Trigger_R", &WiiMoteEmu::WiiMapping[i].AxisMapping.Tr, 1005);
section.Get("DeadZoneL", &WiiMoteEmu::WiiMapping[i].DeadZoneL, 0);
section.Get("DeadZoneR", &WiiMoteEmu::WiiMapping[i].DeadZoneR, 0);
section.Get("Diagonal", &WiiMoteEmu::WiiMapping[i].Diagonal, 100);
section.Get("Circle2Square", &WiiMoteEmu::WiiMapping[i].bCircle2Square, false);
section.Get("Rumble", &WiiMoteEmu::WiiMapping[i].Rumble, false);
section.Get("RumbleStrength", &WiiMoteEmu::WiiMapping[i].RumbleStrength, 80);
section.Get("TriggerType", &WiiMoteEmu::WiiMapping[i].TriggerType, 0);
iniFile.Get(SectionName, "Axis_Lx", &WiiMoteEmu::WiiMapping[i].AxisMapping.Lx, 0);
iniFile.Get(SectionName, "Axis_Ly", &WiiMoteEmu::WiiMapping[i].AxisMapping.Ly, 1);
iniFile.Get(SectionName, "Axis_Rx", &WiiMoteEmu::WiiMapping[i].AxisMapping.Rx, 2);
iniFile.Get(SectionName, "Axis_Ry", &WiiMoteEmu::WiiMapping[i].AxisMapping.Ry, 3);
iniFile.Get(SectionName, "Trigger_L", &WiiMoteEmu::WiiMapping[i].AxisMapping.Tl, 1004);
iniFile.Get(SectionName, "Trigger_R", &WiiMoteEmu::WiiMapping[i].AxisMapping.Tr, 1005);
iniFile.Get(SectionName, "DeadZoneL", &WiiMoteEmu::WiiMapping[i].DeadZoneL, 0);
iniFile.Get(SectionName, "DeadZoneR", &WiiMoteEmu::WiiMapping[i].DeadZoneR, 0);
iniFile.Get(SectionName, "Diagonal", &WiiMoteEmu::WiiMapping[i].Diagonal, 100);
iniFile.Get(SectionName, "Circle2Square", &WiiMoteEmu::WiiMapping[i].bCircle2Square, false);
iniFile.Get(SectionName, "Rumble", &WiiMoteEmu::WiiMapping[i].Rumble, false);
iniFile.Get(SectionName, "RumbleStrength", &WiiMoteEmu::WiiMapping[i].RumbleStrength, 80);
iniFile.Get(SectionName, "TriggerType", &WiiMoteEmu::WiiMapping[i].TriggerType, 0);
//UDPWii
section.Get("UDPWii_Enable", &WiiMoteEmu::WiiMapping[i].UDPWM.enable, false);
iniFile.Get(SectionName, "UDPWii_Enable", &WiiMoteEmu::WiiMapping[i].UDPWM.enable, false);
std::string port;
char default_port[15];
sprintf(default_port,"%d",4432+i);
section.Get("UDPWii_Port", &port, default_port);
iniFile.Get(SectionName, "UDPWii_Port", &port, default_port);
strncpy(WiiMoteEmu::WiiMapping[i].UDPWM.port,port.c_str(),10);
section.Get("UDPWii_EnableAccel", &WiiMoteEmu::WiiMapping[i].UDPWM.enableAccel, true);
section.Get("UDPWii_EnableButtons", &WiiMoteEmu::WiiMapping[i].UDPWM.enableButtons, true);
section.Get("UDPWii_EnableIR", &WiiMoteEmu::WiiMapping[i].UDPWM.enableIR, true);
section.Get("UDPWii_EnableNunchuck", &WiiMoteEmu::WiiMapping[i].UDPWM.enableNunchuck, true);
iniFile.Get(SectionName, "UDPWii_EnableAccel", &WiiMoteEmu::WiiMapping[i].UDPWM.enableAccel, true);
iniFile.Get(SectionName, "UDPWii_EnableButtons", &WiiMoteEmu::WiiMapping[i].UDPWM.enableButtons, true);
iniFile.Get(SectionName, "UDPWii_EnableIR", &WiiMoteEmu::WiiMapping[i].UDPWM.enableIR, true);
iniFile.Get(SectionName, "UDPWii_EnableNunchuck", &WiiMoteEmu::WiiMapping[i].UDPWM.enableNunchuck, true);
}
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Dolphin.ini").c_str());
@ -349,7 +346,7 @@ void Config::Load()
{
char SectionName[32];
sprintf(SectionName, "Wiimote%i", i + 1);
iniFile[SectionName].Get("AutoReconnectRealWiimote", &WiiMoteEmu::WiiMapping[i].bWiiAutoReconnect, false);
iniFile.Get(SectionName, "AutoReconnectRealWiimote", &WiiMoteEmu::WiiMapping[i].bWiiAutoReconnect, false);
}
Config::LoadIR();
@ -357,10 +354,9 @@ void Config::Load()
// Load a few screen settings to. If these are added to the DirectX plugin it's probably
// better to place them in the main Dolphin.ini file
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str());
Section& settings = iniFile["Settings"];
settings.Get("KeepAR_4_3", &bKeepAR43, false);
settings.Get("KeepAR_16_9", &bKeepAR169, false);
settings.Get("Crop", &bCrop, false);
iniFile.Get("Settings", "KeepAR_4_3", &bKeepAR43, false);
iniFile.Get("Settings", "KeepAR_16_9", &bKeepAR169, false);
iniFile.Get("Settings", "Crop", &bCrop, false);
//DEBUG_LOG(WIIMOTE, "Load()");
}
@ -372,23 +368,21 @@ void Config::LoadIR()
char TmpSection[32];
int defaultLeft, defaultTop, defaultWidth, defaultHeight;
sprintf(TmpSection, "%s", g_ISOId ? Hex2Ascii(g_ISOId).c_str() : "Default");
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "IrPointer.ini").c_str());
//Load defaults first...
Section& def = iniFile["Default"];
def.Get("IRLeft", &defaultLeft, LEFT);
def.Get("IRTop", &defaultTop, TOP);
def.Get("IRWidth", &defaultWidth, RIGHT - LEFT);
def.Get("IRHeight", &defaultHeight, BOTTOM - TOP);
def.Get("IRLevel", &iIRLevel, 3);
iniFile.Get("Default", "IRLeft", &defaultLeft, LEFT);
iniFile.Get("Default", "IRTop", &defaultTop, TOP);
iniFile.Get("Default", "IRWidth", &defaultWidth, RIGHT - LEFT);
iniFile.Get("Default", "IRHeight", &defaultHeight, BOTTOM - TOP);
iniFile.Get("Default", "IRLevel", &iIRLevel, 3);
//...and fall back to them if the GameId is not found.
//It shouldn't matter if we read Default twice, its in memory anyways.
sprintf(TmpSection, "%s", g_ISOId ? Hex2Ascii(g_ISOId).c_str() : "Default");
Section& tmpsection = iniFile[TmpSection];
tmpsection.Get("IRLeft", &iIRLeft, defaultLeft);
tmpsection.Get("IRTop", &iIRTop, defaultTop);
tmpsection.Get("IRWidth", &iIRWidth, defaultWidth);
tmpsection.Get("IRHeight", &iIRHeight, defaultHeight);
iniFile.Get(TmpSection, "IRLeft", &iIRLeft, defaultLeft);
iniFile.Get(TmpSection, "IRTop", &iIRTop, defaultTop);
iniFile.Get(TmpSection, "IRWidth", &iIRWidth, defaultWidth);
iniFile.Get(TmpSection, "IRHeight", &iIRHeight, defaultHeight);
}
void Config::Save()
@ -396,74 +390,72 @@ void Config::Save()
IniFile iniFile;
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Wiimote.ini").c_str());
Section& real = iniFile["Real"];
real.Set("UpdateStatus", bUpdateRealWiimote);
real.Set("Unpair", bUnpairRealWiimote);
real.Set("Autopair", bPairRealWiimote);
real.Set("Timeout", bWiiReadTimeout);
real.Set("AccNeutralX", iAccNeutralX);
real.Set("AccNeutralY", iAccNeutralY);
real.Set("AccNeutralZ", iAccNeutralZ);
real.Set("AccNunNeutralX", iAccNunNeutralX);
real.Set("AccNunNeutralY", iAccNunNeutralY);
real.Set("AccNunNeutralZ", iAccNunNeutralZ);
iniFile.Set("Real", "UpdateStatus", bUpdateRealWiimote);
iniFile.Set("Real", "Unpair", bUnpairRealWiimote);
iniFile.Set("Real", "Autopair", bPairRealWiimote);
iniFile.Set("Real", "Timeout", bWiiReadTimeout);
iniFile.Set("Real", "AccNeutralX", iAccNeutralX);
iniFile.Set("Real", "AccNeutralY", iAccNeutralY);
iniFile.Set("Real", "AccNeutralZ", iAccNeutralZ);
iniFile.Set("Real", "AccNunNeutralX", iAccNunNeutralX);
iniFile.Set("Real", "AccNunNeutralY", iAccNunNeutralY);
iniFile.Set("Real", "AccNunNeutralZ", iAccNunNeutralZ);
for (int i = 0; i < MAX_WIIMOTES; i++)
{
// Slot specific settings
char SectionName[32];
sprintf(SectionName, "Wiimote%i", i + 1);
Section& section = iniFile[SectionName];
section.Set("Source", WiiMoteEmu::WiiMapping[i].Source);
section.Set("Sideways", WiiMoteEmu::WiiMapping[i].bSideways);
section.Set("Upright", WiiMoteEmu::WiiMapping[i].bUpright);
section.Set("ExtensionConnected", WiiMoteEmu::WiiMapping[i].iExtensionConnected);
section.Set("MotionPlusConnected", WiiMoteEmu::WiiMapping[i].bMotionPlusConnected);
section.Set("TiltInputWM", WiiMoteEmu::WiiMapping[i].Tilt.InputWM);
section.Set("TiltInputNC", WiiMoteEmu::WiiMapping[i].Tilt.InputNC);
section.Set("TiltRollDegree", WiiMoteEmu::WiiMapping[i].Tilt.RollDegree);
section.Set("TiltRollSwing", WiiMoteEmu::WiiMapping[i].Tilt.RollSwing);
section.Set("TiltRollInvert", WiiMoteEmu::WiiMapping[i].Tilt.RollInvert);
section.Set("TiltPitchDegree", WiiMoteEmu::WiiMapping[i].Tilt.PitchDegree);
section.Set("TiltPitchSwing", WiiMoteEmu::WiiMapping[i].Tilt.PitchSwing);
section.Set("TiltPitchInvert", WiiMoteEmu::WiiMapping[i].Tilt.PitchInvert);
iniFile.Set(SectionName, "Source", WiiMoteEmu::WiiMapping[i].Source);
iniFile.Set(SectionName, "Sideways", WiiMoteEmu::WiiMapping[i].bSideways);
iniFile.Set(SectionName, "Upright", WiiMoteEmu::WiiMapping[i].bUpright);
iniFile.Set(SectionName, "ExtensionConnected", WiiMoteEmu::WiiMapping[i].iExtensionConnected);
iniFile.Set(SectionName, "MotionPlusConnected", WiiMoteEmu::WiiMapping[i].bMotionPlusConnected);
iniFile.Set(SectionName, "TiltInputWM", WiiMoteEmu::WiiMapping[i].Tilt.InputWM);
iniFile.Set(SectionName, "TiltInputNC", WiiMoteEmu::WiiMapping[i].Tilt.InputNC);
iniFile.Set(SectionName, "TiltRollDegree", WiiMoteEmu::WiiMapping[i].Tilt.RollDegree);
iniFile.Set(SectionName, "TiltRollSwing", WiiMoteEmu::WiiMapping[i].Tilt.RollSwing);
iniFile.Set(SectionName, "TiltRollInvert", WiiMoteEmu::WiiMapping[i].Tilt.RollInvert);
iniFile.Set(SectionName, "TiltPitchDegree", WiiMoteEmu::WiiMapping[i].Tilt.PitchDegree);
iniFile.Set(SectionName, "TiltPitchSwing", WiiMoteEmu::WiiMapping[i].Tilt.PitchSwing);
iniFile.Set(SectionName, "TiltPitchInvert", WiiMoteEmu::WiiMapping[i].Tilt.PitchInvert);
// StickMapping
section.Set("NCStick", WiiMoteEmu::WiiMapping[i].Stick.NC);
section.Set("CCStickLeft", WiiMoteEmu::WiiMapping[i].Stick.CCL);
section.Set("CCStickRight", WiiMoteEmu::WiiMapping[i].Stick.CCR);
section.Set("CCTriggers", WiiMoteEmu::WiiMapping[i].Stick.CCT);
section.Set("GHStick", WiiMoteEmu::WiiMapping[i].Stick.GH);
iniFile.Set(SectionName, "NCStick", WiiMoteEmu::WiiMapping[i].Stick.NC);
iniFile.Set(SectionName, "CCStickLeft", WiiMoteEmu::WiiMapping[i].Stick.CCL);
iniFile.Set(SectionName, "CCStickRight", WiiMoteEmu::WiiMapping[i].Stick.CCR);
iniFile.Set(SectionName, "CCTriggers", WiiMoteEmu::WiiMapping[i].Stick.CCT);
iniFile.Set(SectionName, "GHStick", WiiMoteEmu::WiiMapping[i].Stick.GH);
// ButtonMapping
for (int x = 0; x < WiiMoteEmu::LAST_CONSTANT; x++)
section.Set(wmControlNames[x], WiiMoteEmu::WiiMapping[i].Button[x]);
iniFile.Set(SectionName, wmControlNames[x], WiiMoteEmu::WiiMapping[i].Button[x]);
// Save the physical device ID number
section.Set("DeviceID", WiiMoteEmu::WiiMapping[i].ID);
iniFile.Set(SectionName, "DeviceID", WiiMoteEmu::WiiMapping[i].ID);
section.Set("Axis_Lx", WiiMoteEmu::WiiMapping[i].AxisMapping.Lx);
section.Set("Axis_Ly", WiiMoteEmu::WiiMapping[i].AxisMapping.Ly);
section.Set("Axis_Rx", WiiMoteEmu::WiiMapping[i].AxisMapping.Rx);
section.Set("Axis_Ry", WiiMoteEmu::WiiMapping[i].AxisMapping.Ry);
section.Set("Trigger_L", WiiMoteEmu::WiiMapping[i].AxisMapping.Tl);
section.Set("Trigger_R", WiiMoteEmu::WiiMapping[i].AxisMapping.Tr);
section.Set("DeadZoneL", WiiMoteEmu::WiiMapping[i].DeadZoneL);
section.Set("DeadZoneR", WiiMoteEmu::WiiMapping[i].DeadZoneR);
section.Set("Diagonal", WiiMoteEmu::WiiMapping[i].Diagonal);
section.Set("Circle2Square", WiiMoteEmu::WiiMapping[i].bCircle2Square);
section.Set("Rumble", WiiMoteEmu::WiiMapping[i].Rumble);
section.Set("RumbleStrength", WiiMoteEmu::WiiMapping[i].RumbleStrength);
section.Set("TriggerType", WiiMoteEmu::WiiMapping[i].TriggerType);
iniFile.Set(SectionName, "Axis_Lx", WiiMoteEmu::WiiMapping[i].AxisMapping.Lx);
iniFile.Set(SectionName, "Axis_Ly", WiiMoteEmu::WiiMapping[i].AxisMapping.Ly);
iniFile.Set(SectionName, "Axis_Rx", WiiMoteEmu::WiiMapping[i].AxisMapping.Rx);
iniFile.Set(SectionName, "Axis_Ry", WiiMoteEmu::WiiMapping[i].AxisMapping.Ry);
iniFile.Set(SectionName, "Trigger_L", WiiMoteEmu::WiiMapping[i].AxisMapping.Tl);
iniFile.Set(SectionName, "Trigger_R", WiiMoteEmu::WiiMapping[i].AxisMapping.Tr);
iniFile.Set(SectionName, "DeadZoneL", WiiMoteEmu::WiiMapping[i].DeadZoneL);
iniFile.Set(SectionName, "DeadZoneR", WiiMoteEmu::WiiMapping[i].DeadZoneR);
iniFile.Set(SectionName, "Diagonal", WiiMoteEmu::WiiMapping[i].Diagonal);
iniFile.Set(SectionName, "Circle2Square", WiiMoteEmu::WiiMapping[i].bCircle2Square);
iniFile.Set(SectionName, "Rumble", WiiMoteEmu::WiiMapping[i].Rumble);
iniFile.Set(SectionName, "RumbleStrength", WiiMoteEmu::WiiMapping[i].RumbleStrength);
iniFile.Set(SectionName, "TriggerType", WiiMoteEmu::WiiMapping[i].TriggerType);
// UDPWii
section.Set("UDPWii_Enable", WiiMoteEmu::WiiMapping[i].UDPWM.enable);
section.Set("UDPWii_Port", WiiMoteEmu::WiiMapping[i].UDPWM.port);
section.Set("UDPWii_EnableAccel", WiiMoteEmu::WiiMapping[i].UDPWM.enableAccel);
section.Set("UDPWii_EnableButtons", WiiMoteEmu::WiiMapping[i].UDPWM.enableButtons);
section.Set("UDPWii_EnableIR", WiiMoteEmu::WiiMapping[i].UDPWM.enableIR);
section.Set("UDPWii_EnableNunchuck", WiiMoteEmu::WiiMapping[i].UDPWM.enableNunchuck);
iniFile.Set(SectionName, "UDPWii_Enable", WiiMoteEmu::WiiMapping[i].UDPWM.enable);
iniFile.Set(SectionName, "UDPWii_Port", WiiMoteEmu::WiiMapping[i].UDPWM.port);
iniFile.Set(SectionName, "UDPWii_EnableAccel", WiiMoteEmu::WiiMapping[i].UDPWM.enableAccel);
iniFile.Set(SectionName, "UDPWii_EnableButtons", WiiMoteEmu::WiiMapping[i].UDPWM.enableButtons);
iniFile.Set(SectionName, "UDPWii_EnableIR", WiiMoteEmu::WiiMapping[i].UDPWM.enableIR);
iniFile.Set(SectionName, "UDPWii_EnableNunchuck", WiiMoteEmu::WiiMapping[i].UDPWM.enableNunchuck);
}
iniFile.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Wiimote.ini").c_str());
@ -472,12 +464,11 @@ void Config::Save()
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "IrPointer.ini").c_str());
char TmpSection[32];
sprintf(TmpSection, "%s", g_ISOId ? Hex2Ascii(g_ISOId).c_str() : "Default");
Section& tmpsection = iniFile[TmpSection];
tmpsection.Set("IRLeft", iIRLeft);
tmpsection.Set("IRTop", iIRTop);
tmpsection.Set("IRWidth", iIRWidth);
tmpsection.Set("IRHeight", iIRHeight);
tmpsection.Set("IRLevel", iIRLevel);
iniFile.Set(TmpSection, "IRLeft", iIRLeft);
iniFile.Set(TmpSection, "IRTop", iIRTop);
iniFile.Set(TmpSection, "IRWidth", iIRWidth);
iniFile.Set(TmpSection, "IRHeight", iIRHeight);
iniFile.Set(TmpSection, "IRLevel", iIRLevel);
iniFile.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "IrPointer.ini").c_str());
//Save any options that need to be accessed in Dolphin
@ -486,7 +477,7 @@ void Config::Save()
{
char SectionName[32];
sprintf(SectionName, "Wiimote%i", i + 1);
iniFile[SectionName].Set("AutoReconnectRealWiimote", WiiMoteEmu::WiiMapping[i].bWiiAutoReconnect);
iniFile.Set(SectionName, "AutoReconnectRealWiimote", WiiMoteEmu::WiiMapping[i].bWiiAutoReconnect);
}
iniFile.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Dolphin.ini").c_str());

View File

@ -42,32 +42,31 @@ void WiimoteRecordingConfigDialog::LoadFile()
// Get row name
std::string SaveName = StringFromFormat("Recording%i", i);
Section& section = file[SaveName.c_str()];
// HotKey
section.Get("HotKeySwitch", &iTmp, 3); m_RecordHotKeySwitch[i]->SetSelection(iTmp);
section.Get("HotKeyWiimote", &iTmp, 10); m_RecordHotKeyWiimote[i]->SetSelection(iTmp);
section.Get("HotKeyNunchuck", &iTmp, 10); m_RecordHotKeyNunchuck[i]->SetSelection(iTmp);
section.Get("HotKeyIR", &iTmp, 10); m_RecordHotKeyIR[i]->SetSelection(iTmp);
file.Get(SaveName.c_str(), "HotKeySwitch", &iTmp, 3); m_RecordHotKeySwitch[i]->SetSelection(iTmp);
file.Get(SaveName.c_str(), "HotKeyWiimote", &iTmp, 10); m_RecordHotKeyWiimote[i]->SetSelection(iTmp);
file.Get(SaveName.c_str(), "HotKeyNunchuck", &iTmp, 10); m_RecordHotKeyNunchuck[i]->SetSelection(iTmp);
file.Get(SaveName.c_str(), "HotKeyIR", &iTmp, 10); m_RecordHotKeyIR[i]->SetSelection(iTmp);
// Movement name
section.Get("MovementName", &STmp, ""); m_RecordText[i]->SetValue(wxString::FromAscii(STmp.c_str()));
file.Get(SaveName.c_str(), "MovementName", &STmp, ""); m_RecordText[i]->SetValue(wxString::FromAscii(STmp.c_str()));
// Game name
section.Get("GameName", &STmp, ""); m_RecordGameText[i]->SetValue(wxString::FromAscii(STmp.c_str()));
file.Get(SaveName.c_str(), "GameName", &STmp, ""); m_RecordGameText[i]->SetValue(wxString::FromAscii(STmp.c_str()));
// IR Bytes
section.Get("IRBytes", &STmp, ""); m_RecordIRBytesText[i]->SetValue(wxString::FromAscii(STmp.c_str()));
file.Get(SaveName.c_str(), "IRBytes", &STmp, ""); m_RecordIRBytesText[i]->SetValue(wxString::FromAscii(STmp.c_str()));
// Recording speed
section.Get("RecordingSpeed", &iTmp, -1);
file.Get(SaveName.c_str(), "RecordingSpeed", &iTmp, -1);
if(iTmp != -1)
m_RecordSpeed[i]->SetValue(wxString::Format(wxT("%i"), iTmp));
else
m_RecordSpeed[i]->SetValue(wxT(""));
// Playback speed (currently always saved directly after a recording)
section.Get("PlaybackSpeed", &iTmp, -1); m_RecordPlayBackSpeed[i]->SetSelection(iTmp);
file.Get(SaveName.c_str(), "PlaybackSpeed", &iTmp, -1); m_RecordPlayBackSpeed[i]->SetSelection(iTmp);
}
}
@ -82,31 +81,30 @@ void WiimoteRecordingConfigDialog::SaveFile()
{
// Get row name
std::string SaveName = StringFromFormat("Recording%i", i);
Section& section = file[SaveName.c_str()];
// HotKey
section.Set("HotKeySwitch", m_RecordHotKeySwitch[i]->GetSelection());
section.Set("HotKeyWiimote", m_RecordHotKeyWiimote[i]->GetSelection());
section.Set("HotKeyNunchuck", m_RecordHotKeyNunchuck[i]->GetSelection());
section.Set("HotKeyIR", m_RecordHotKeyIR[i]->GetSelection());
file.Set(SaveName.c_str(), "HotKeySwitch", m_RecordHotKeySwitch[i]->GetSelection());
file.Set(SaveName.c_str(), "HotKeyWiimote", m_RecordHotKeyWiimote[i]->GetSelection());
file.Set(SaveName.c_str(), "HotKeyNunchuck", m_RecordHotKeyNunchuck[i]->GetSelection());
file.Set(SaveName.c_str(), "HotKeyIR", m_RecordHotKeyIR[i]->GetSelection());
// Movement name
section.Set("MovementName", (const char*)m_RecordText[i]->GetValue().mb_str(wxConvUTF8));
file.Set(SaveName.c_str(), "MovementName", (const char*)m_RecordText[i]->GetValue().mb_str(wxConvUTF8));
// Game name
section.Set("GameName", (const char*)m_RecordGameText[i]->GetValue().mb_str(wxConvUTF8));
file.Set(SaveName.c_str(), "GameName", (const char*)m_RecordGameText[i]->GetValue().mb_str(wxConvUTF8));
// Recording speed (currently always saved directly after a recording)
/*
wxString TmpRecordSpeed = m_RecordSpeed[i]->GetValue();
if(TmpRecordSpeed.length() > 0)
int TmpRecordSpeed; section.Set("RecordingSpeed", TmpRecordSpeed);
int TmpRecordSpeed; file.Set(SaveName.c_str(), "RecordingSpeed", TmpRecordSpeed);
else
int TmpRecordSpeed; section.Set("RecordingSpeed", "-1");
int TmpRecordSpeed; file.Set(SaveName.c_str(), "RecordingSpeed", "-1");
*/
// Playback speed (currently always saved directly after a recording)
section.Set("PlaybackSpeed", m_RecordPlayBackSpeed[i]->GetSelection());
file.Set(SaveName.c_str(), "PlaybackSpeed", m_RecordPlayBackSpeed[i]->GetSelection());
}
file.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "WiimoteMovement.ini").c_str());
@ -421,19 +419,17 @@ void WiimoteRecordingConfigDialog::ConvertToString()
// Save file
std::string SaveName = StringFromFormat("Recording%i", m_iRecordTo);
Section& section = file[SaveName];
section.Set("Movement", TmpStr);
section.Set("IR", TmpIR);
section.Set("Time", TmpTime);
section.Set("IRBytes", IRBytes);
section.Set("RecordingSpeed", Rate);
file.Set(SaveName.c_str(), "Movement", TmpStr.c_str());
file.Set(SaveName.c_str(), "IR", TmpIR.c_str());
file.Set(SaveName.c_str(), "Time", TmpTime.c_str());
file.Set(SaveName.c_str(), "IRBytes", IRBytes);
file.Set(SaveName.c_str(), "RecordingSpeed", Rate);
// Set a default playback speed if none is set already
int TmpPlaySpeed; section.Get("PlaybackSpeed", &TmpPlaySpeed, -1);
int TmpPlaySpeed; file.Get(SaveName.c_str(), "PlaybackSpeed", &TmpPlaySpeed, -1);
if (TmpPlaySpeed == -1)
{
section.Set("PlaybackSpeed", 3);
file.Set(SaveName.c_str(), "PlaybackSpeed", 3);
m_RecordPlayBackSpeed[m_iRecordTo]->SetSelection(3);
}

View File

@ -116,23 +116,19 @@ void LoadRecordedMovements()
VRecording.at(i).Recording.clear();
// Get row name
Section& section = file[StringFromFormat("Recording%i", i + 1)];
std::string SaveName = StringFromFormat("Recording%i", i + 1);
// Get movement
std::string TmpMovement;
section.Get("Movement", &TmpMovement, "");
std::string TmpMovement; file.Get(SaveName.c_str(), "Movement", &TmpMovement, "");
// Get IR
std::string TmpIR;
section.Get("IR", &TmpIR, "");
std::string TmpIR; file.Get(SaveName.c_str(), "IR", &TmpIR, "");
// Get time
std::string TmpTime;
section.Get("Time", &TmpTime, "");
std::string TmpTime; file.Get(SaveName.c_str(), "Time", &TmpTime, "");
// Get IR bytes
int TmpIRBytes;
section.Get("IRBytes", &TmpIRBytes, 0);
int TmpIRBytes; file.Get(SaveName.c_str(), "IRBytes", &TmpIRBytes, 0);
VRecording.at(i).IRBytes = TmpIRBytes;
SRecording Tmp;
@ -185,13 +181,13 @@ void LoadRecordedMovements()
}
// Get HotKey
section.Get("HotKeySwitch", &iTmp, 3); VRecording.at(i).HotKeySwitch = iTmp;
section.Get("HotKeyWiimote", &iTmp, 10); VRecording.at(i).HotKeyWiimote = iTmp;
section.Get("HotKeyNunchuck", &iTmp, 10); VRecording.at(i).HotKeyNunchuck = iTmp;
section.Get("HotKeyIR", &iTmp, 10); VRecording.at(i).HotKeyIR = iTmp;
file.Get(SaveName.c_str(), "HotKeySwitch", &iTmp, 3); VRecording.at(i).HotKeySwitch = iTmp;
file.Get(SaveName.c_str(), "HotKeyWiimote", &iTmp, 10); VRecording.at(i).HotKeyWiimote = iTmp;
file.Get(SaveName.c_str(), "HotKeyNunchuck", &iTmp, 10); VRecording.at(i).HotKeyNunchuck = iTmp;
file.Get(SaveName.c_str(), "HotKeyIR", &iTmp, 10); VRecording.at(i).HotKeyIR = iTmp;
// Get Recording speed
int TmpPlaybackSpeed; section.Get("PlaybackSpeed", &TmpPlaybackSpeed, -1);
int TmpPlaybackSpeed; file.Get(SaveName.c_str(), "PlaybackSpeed", &TmpPlaybackSpeed, -1);
VRecording.at(i).PlaybackSpeed = TmpPlaybackSpeed;
// Logging

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="Plugin_WiimoteNew"
ProjectGUID="{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}"
RootNamespace="Plugin_WiimoteNew"
@ -44,7 +44,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputUICommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -130,7 +130,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputUICommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -213,7 +213,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputUICommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS"
RuntimeLibrary="0"
AssemblerListingLocation="$(IntDir)\"
@ -299,7 +299,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputUICommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS"
RuntimeLibrary="0"
AssemblerListingLocation="$(IntDir)\"
@ -382,7 +382,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputUICommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="DEBUGFAST;WIN32;NDEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
WarningLevel="3"
@ -465,7 +465,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputUICommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;DEBUGFAST;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
WarningLevel="3"

View File

@ -20,7 +20,7 @@ files = [
]
wiinewenv.Append(
LIBS = [ 'inputuicommon', 'inputcommon', 'common' ],
LIBS = [ 'inputplugincommon', 'inputcommon', 'common' ],
)
if sys.platform == 'darwin':

View File

@ -66,7 +66,7 @@ void Wiimote::ReportMode(const u16 _channelID, wm_report_mode* dr)
m_reporting_channel = _channelID;
// reset IR camera
//memset(m_reg_ir, 0, sizeof(*m_reg_ir)); //ugly hack
memset(m_reg_ir, 0, sizeof(*m_reg_ir));
if (0 == dr->all_the_time)
PanicAlert("Wiimote: Reporting Always is set to OFF! Everything should be fine, but games never do this.");

View File

@ -484,8 +484,26 @@ void Wiimote::Update()
}
// ----extension----
if (rpt.ext)
{
m_extension->GetState(data + rpt.ext, is_focus);
// i dont think anything accesses the extension data like this, but ill support it
// i think it should be unencrpyted in the register, encrypted when read
memcpy(m_reg_ext->controller_data, data + rpt.ext, sizeof(wm_extension));
// both of these ifs work
//if (0x55 != m_reg_ext->encryption)
if (0xAA == m_reg_ext->encryption)
wiimote_encrypt(&m_ext_key, data + rpt.ext, 0x00, sizeof(wm_extension));
}
// ----ir----
if (rpt.ir)
// only if camera is fully enabled.
// should send 0xFF if camera isn't enabled maybe,
// 0x00 is working fine though
if (rpt.ir && 0x08 == m_reg_ir->data[0x30])
{
float xx = 10000, yy = 0, zz = 0;
@ -508,21 +526,14 @@ void Wiimote::Update()
x[1] = (unsigned int)(xx + distance);
x[2] = (unsigned int)(xx - 1.2f * distance);
x[3] = (unsigned int)(xx + 1.2f * distance);
//0xFF report
if (rpt.ext)
memset(data + rpt.ir, 0xFF, (rpt.ext - rpt.ir));
else
memset(data + rpt.ir, 0xFF, (46 - rpt.ir));
//Fill report with valid data when full handshake was done
if (m_reg_ir->data[0x30] || m_reg_ir->data[0x33])
// ir mode
switch (m_reg_ir->mode)
{
// basic
case 1 :
{
memset(data + rpt.ir, 0xFF, 10);
wm_ir_basic* const irdata = (wm_ir_basic*)(data + rpt.ir);
if (y < 768)
{
@ -551,6 +562,7 @@ void Wiimote::Update()
// extended
case 3 :
{
memset(data + rpt.ir, 0xFF, 12);
wm_ir_extended* const irdata = (wm_ir_extended*)(data + rpt.ir);
if (y < 768)
{
@ -572,22 +584,10 @@ void Wiimote::Update()
case 5 :
// UNSUPPORTED
break;
}
}
// ----extension----
if (rpt.ext)
{
m_extension->GetState(data + rpt.ext, is_focus);
// i dont think anything accesses the extension data like this, but ill support it. Indeed, commercial games don't do this.
// i think it should be unencrpyted in the register, encrypted when read.
memcpy(m_reg_ext->controller_data, data + rpt.ext, sizeof(wm_extension));
if (0xAA == m_reg_ext->encryption) {
wiimote_encrypt(&m_ext_key, data + rpt.ext, 0x00, sizeof(wm_extension));
}
}
// send data report
g_WiimoteInitialize.pWiimoteInput( m_index, m_reporting_channel, data, rpt.size );
}

View File

@ -2,13 +2,13 @@
#include "Common.h"
#include "pluginspecs_wiimote.h"
#include <ControllerInterface/ControllerInterface.h>
#include "ControllerInterface/ControllerInterface.h"
#include "WiimoteEmu/WiimoteEmu.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigDiag.h"
#endif
#include <InputConfig.h>
#include "../../InputPluginCommon/Src/Config.h"
#if defined(HAVE_X11) && HAVE_X11
#include <X11/Xlib.h>