361 lines
8.7 KiB
C++
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
|
|
}
|