dolphin/Source/Plugins/Plugin_GCPadNew/Src/GCPadNew.cpp

361 lines
8.7 KiB
C++

#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;
// if we want background input or have focus
if ( g_plugin.controllers[_numPAD]->options[0].settings[0]->value || g_PADInitialize->pRendererHasFocus() )
{
// get input
((GCPad*)g_plugin.controllers[ _numPAD ])->GetInput( _pPADStatus );
}
else
{
// center sticks
memset( &_pPADStatus->stickX, 0x80, 4 );
// stop rumble
((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( false );
}
// 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() )
{
// only on/off rumble, if we have focus or background input on
if ( g_plugin.controllers[_numPAD]->options[0].settings[0]->value || g_PADInitialize->pRendererHasFocus() )
((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
}