2008-12-08 05:25:12 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// Project description
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
2009-01-15 06:48:15 +00:00
// Name: nJoy
2008-12-08 05:25:12 +00:00
// Description: A Dolphin Compatible Input Plugin
//
// Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net
// Copyright (C) 2003-2008 Dolphin Project.
//
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// 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 "nJoy.h"
//////////////////////////////////////////////////////////////////////////////////////////
// Variables
// ¯¯¯¯¯¯¯¯¯
FILE * pFile ;
CONTROLLER_INFO * joyinfo = 0 ;
CONTROLLER_STATE joystate [ 4 ];
CONTROLLER_MAPPING joysticks [ 4 ];
bool emulator_running = FALSE ;
2009-03-18 17:17:58 +00:00
PLUGIN_GLOBALS * globals = NULL ;
2008-12-22 10:47:37 +00:00
2008-12-08 05:25:12 +00:00
// Handle to window
HWND m_hWnd ;
#ifdef USE_RUMBLE_DINPUT_HACK
bool g_rumbleEnable = FALSE ;
#endif
2009-01-23 21:28:55 +00:00
2008-12-08 05:25:12 +00:00
// Rumble in windows
#ifdef _WIN32
2008-12-23 08:49:52 +00:00
HINSTANCE nJoy_hInst = NULL ;
2008-12-08 05:25:12 +00:00
#ifdef USE_RUMBLE_DINPUT_HACK
LPDIRECTINPUT8 g_pDI = NULL ;
LPDIRECTINPUTDEVICE8 g_pDevice = NULL ;
LPDIRECTINPUTEFFECT g_pEffect = NULL ;
DWORD g_dwNumForceFeedbackAxis = 0 ;
INT g_nXForce = 0 ;
INT g_nYForce = 0 ;
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
HRESULT InitDirectInput ( HWND hDlg );
VOID FreeDirectInput ();
2008-12-12 17:36:12 +00:00
BOOL CALLBACK EnumFFDevicesCallback ( const DIDEVICEINSTANCE * pInst , VOID * pContext );
BOOL CALLBACK EnumAxesCallback ( const DIDEVICEOBJECTINSTANCE * pdidoi , VOID * pContext );
2008-12-08 05:25:12 +00:00
HRESULT SetDeviceForcesXY ();
#endif
#elif defined(__linux__)
int fd ;
char device_file_name [ 64 ];
struct ff_effect effect ;
bool CanRumble = false ;
#endif
2008-12-23 08:49:52 +00:00
#ifdef _WIN32
2009-01-05 22:11:08 +00:00
#if defined(HAVE_WX) && HAVE_WX
2008-12-08 05:25:12 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// wxWidgets
// ¯¯¯¯¯¯¯¯¯
class wxDLLApp : public wxApp
{
bool OnInit ()
{
return true ;
}
};
2009-01-15 06:48:15 +00:00
IMPLEMENT_APP_NO_MAIN ( wxDLLApp )
2008-12-08 05:25:12 +00:00
WXDLLIMPEXP_BASE void wxSetInstance ( HINSTANCE hInst );
2009-01-05 22:11:08 +00:00
#endif
2008-12-08 05:25:12 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
2009-01-15 06:48:15 +00:00
// DllMain
2008-12-08 05:25:12 +00:00
// ¯¯¯¯¯¯¯
2008-12-23 08:49:52 +00:00
2008-12-08 05:25:12 +00:00
BOOL APIENTRY DllMain ( HINSTANCE hinstDLL , // DLL module handle
DWORD dwReason , // reason called
LPVOID lpvReserved ) // reserved
2009-01-15 06:48:15 +00:00
{
2008-12-08 05:25:12 +00:00
switch ( dwReason )
{
case DLL_PROCESS_ATTACH :
{
2009-01-05 22:11:08 +00:00
#if defined(HAVE_WX) && HAVE_WX
2008-12-08 05:25:12 +00:00
//use wxInitialize() if you don't want GUI instead of the following 12 lines
wxSetInstance (( HINSTANCE ) hinstDLL );
int argc = 0 ;
char ** argv = NULL ;
wxEntryStart ( argc , argv );
if ( ! wxTheApp || ! wxTheApp -> CallOnInit () )
return FALSE ;
2009-01-05 22:11:08 +00:00
#endif
2008-12-08 05:25:12 +00:00
}
2009-01-15 06:48:15 +00:00
break ;
2008-12-08 05:25:12 +00:00
case DLL_PROCESS_DETACH :
2009-01-05 22:11:08 +00:00
#if defined(HAVE_WX) && HAVE_WX
2009-01-15 06:48:15 +00:00
wxEntryCleanup (); //use wxUninitialize() if you don't want GUI
2009-01-05 22:11:08 +00:00
#endif
2008-12-08 05:25:12 +00:00
break ;
default :
break ;
}
2009-01-15 06:48:15 +00:00
nJoy_hInst = hinstDLL ;
2008-12-08 05:25:12 +00:00
return TRUE ;
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// Input Plugin Functions (from spec's)
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Get properties of plugin
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void GetDllInfo ( PLUGIN_INFO * _PluginInfo )
{
_PluginInfo -> Version = 0x0100 ;
_PluginInfo -> Type = PLUGIN_TYPE_PAD ;
2009-01-15 06:48:15 +00:00
#ifdef DEBUGFAST
2008-12-08 05:25:12 +00:00
sprintf ( _PluginInfo -> Name , "nJoy v" INPUT_VERSION " (DebugFast) by Falcon4ever" );
#else
#ifndef _DEBUG
sprintf ( _PluginInfo -> Name , "nJoy v" INPUT_VERSION " by Falcon4ever" );
#else
sprintf ( _PluginInfo -> Name , "nJoy v" INPUT_VERSION " (Debug) by Falcon4ever" );
#endif
#endif
}
2009-03-18 17:17:58 +00:00
void SetDllGlobals ( PLUGIN_GLOBALS * _pPluginGlobals )
{
globals = _pPluginGlobals ;
LogManager :: SetInstance (( LogManager * ) globals -> logManager );
2009-01-08 12:12:15 +00:00
}
2009-03-18 17:17:58 +00:00
2008-12-08 05:25:12 +00:00
// Call config dialog
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void DllConfig ( HWND _hParent )
2009-01-23 21:28:55 +00:00
{
# ifdef _WIN32
if ( SDL_Init ( SDL_INIT_JOYSTICK ) < 0 )
2008-12-08 05:25:12 +00:00
{
2009-01-23 21:28:55 +00:00
MessageBox ( NULL , SDL_GetError (), "Could not initialize SDL!" , MB_ICONERROR );
return ;
2008-12-08 05:25:12 +00:00
}
2009-01-23 21:28:55 +00:00
LoadConfig (); // load settings
2008-12-08 05:25:12 +00:00
2009-01-23 21:28:55 +00:00
#if defined(HAVE_WX) && HAVE_WX
wxWindow win ;
win . SetHWND ( _hParent );
ConfigBox frame ( & win );
frame . ShowModal ();
win . SetHWND ( 0 );
#endif
#else
if ( SDL_Init ( SDL_INIT_JOYSTICK ) < 0 )
{
printf ( "Could not initialize SDL! (%s) \n " , SDL_GetError ());
return ;
}
LoadConfig (); // load settings
#if defined(HAVE_WX) && HAVE_WX
ConfigBox frame ( NULL );
frame . ShowModal ();
#endif
#endif
2008-12-08 05:25:12 +00:00
}
2008-12-17 17:49:38 +00:00
void DllDebugger ( HWND _hParent , bool Show ) {
}
2008-12-08 05:25:12 +00:00
// Init PAD (start emulation)
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
2009-01-15 06:48:15 +00:00
void Initialize ( void * init )
{
SPADInitialize _PADInitialize = * ( SPADInitialize * ) init ;
2008-12-08 05:25:12 +00:00
emulator_running = TRUE ;
#ifdef _DEBUG
DEBUG_INIT ();
#endif
2009-01-15 06:48:15 +00:00
2009-01-23 21:28:55 +00:00
if ( SDL_Init ( SDL_INIT_JOYSTICK ) < 0 )
{
#ifdef _WIN32
MessageBox ( NULL , SDL_GetError (), "Could not initialize SDL!" , MB_ICONERROR );
#else
printf ( "Could not initialize SDL! (%s) \n " , SDL_GetError ());
#endif
return ;
}
2008-12-08 05:25:12 +00:00
#ifdef _WIN32
2009-01-15 06:48:15 +00:00
m_hWnd = ( HWND ) _PADInitialize . hWnd ;
2008-12-08 05:25:12 +00:00
#endif
LoadConfig (); // Load joystick mapping
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
if ( joysticks [ 0 ]. enabled )
joystate [ 0 ]. joy = SDL_JoystickOpen ( joysticks [ 0 ]. ID );
if ( joysticks [ 1 ]. enabled )
joystate [ 1 ]. joy = SDL_JoystickOpen ( joysticks [ 1 ]. ID );
if ( joysticks [ 2 ]. enabled )
joystate [ 2 ]. joy = SDL_JoystickOpen ( joysticks [ 2 ]. ID );
if ( joysticks [ 3 ]. enabled )
joystate [ 3 ]. joy = SDL_JoystickOpen ( joysticks [ 3 ]. ID );
}
// Shutdown PAD (stop emulation)
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
2009-01-15 06:48:15 +00:00
void Shutdown ()
2008-12-08 05:25:12 +00:00
{
2009-01-23 21:28:55 +00:00
if ( joysticks [ 0 ]. enabled )
SDL_JoystickClose ( joystate [ 0 ]. joy );
if ( joysticks [ 1 ]. enabled )
SDL_JoystickClose ( joystate [ 1 ]. joy );
if ( joysticks [ 2 ]. enabled )
SDL_JoystickClose ( joystate [ 2 ]. joy );
if ( joysticks [ 3 ]. enabled )
SDL_JoystickClose ( joystate [ 3 ]. joy );
SDL_Quit ();
#ifdef _DEBUG
DEBUG_QUIT ();
#endif
2009-01-15 06:48:15 +00:00
delete [] joyinfo ;
2009-01-23 21:28:55 +00:00
emulator_running = FALSE ;
#ifdef _WIN32
#ifdef USE_RUMBLE_DINPUT_HACK
FreeDirectInput ();
#endif
#elif defined(__linux__)
close ( fd );
#endif
2008-12-08 05:25:12 +00:00
}
2009-01-15 06:48:15 +00:00
void DoState ( unsigned char ** ptr , int mode ) {
}
2008-12-28 18:50:24 +00:00
// Set buttons status from wxWidgets in the main application
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
2009-01-19 17:47:00 +00:00
void PAD_Input ( u16 _Key , u8 _UpDown ) {}
2008-12-28 18:50:24 +00:00
2009-01-15 06:48:15 +00:00
2008-12-28 18:50:24 +00:00
2008-12-08 05:25:12 +00:00
// Set PAD status
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void PAD_GetStatus ( u8 _numPAD , SPADStatus * _pPADStatus )
{
if ( ! joysticks [ _numPAD ]. enabled )
return ;
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
// clear pad status
memset ( _pPADStatus , 0 , sizeof ( SPADStatus ));
// get pad status
GetJoyState ( _numPAD );
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
// Reset!
int base = 0x80 ;
_pPADStatus -> stickY = base ;
_pPADStatus -> stickX = base ;
_pPADStatus -> substickX = base ;
_pPADStatus -> substickY = base ;
_pPADStatus -> button |= PAD_USE_ORIGIN ;
// Set analog controllers
// Set Deadzones perhaps out of function
int deadzone = ( int )((( float )( 128.00 / 100.00 )) * ( float )( joysticks [ _numPAD ]. deadzone + 1 ));
int deadzone2 = ( int )((( float )( - 128.00 / 100.00 )) * ( float )( joysticks [ _numPAD ]. deadzone + 1 ));
// Adjust range
// The value returned by SDL_JoystickGetAxis is a signed integer (-32768 to 32768)
// The value used for the gamecube controller is an unsigned char (0 to 255)
2008-12-23 08:49:52 +00:00
int main_stick_x = 0 , main_stick_y = 0 , sub_stick_x = 0 , sub_stick_y = 0 ;
2008-12-10 03:49:17 +00:00
if ( joysticks [ _numPAD ]. buttons [ CTL_MAIN_X ]. c_str ()[ 0 ] == 'A' ) // Axis
{
main_stick_x = ( joystate [ _numPAD ]. buttons [ CTL_MAIN_X ] >> 8 );
main_stick_y = - ( joystate [ _numPAD ]. buttons [ CTL_MAIN_Y ] >> 8 );
sub_stick_x = ( joystate [ _numPAD ]. buttons [ CTL_SUB_X ] >> 8 );
sub_stick_y = - ( joystate [ _numPAD ]. buttons [ CTL_SUB_Y ] >> 8 );
}
else if ( joysticks [ _numPAD ]. buttons [ CTL_MAIN_X ]. c_str ()[ 0 ] == 'B' ) // Button
{
PanicAlert ( "Buttons as Joysticks don't work yet!" );
}
else if ( joysticks [ _numPAD ]. buttons [ CTL_MAIN_X ]. c_str ()[ 0 ] == 'H' ) // Hat
{
PanicAlert ( "Hats as Joysticks don't work yet! \n " );
}
else if ( joysticks [ _numPAD ]. buttons [ CTL_MAIN_X ]. c_str ()[ 0 ] == 'N' ) // None
{}
else // Wtf?
{
//Do a panicAlert here?
}
2008-12-08 05:25:12 +00:00
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
// Quick fix
if ( main_stick_x > 127 )
main_stick_x = 127 ;
if ( main_stick_y > 127 )
main_stick_y = 127 ;
if ( sub_stick_x > 127 )
sub_stick_x = 127 ;
if ( sub_stick_y > 127 )
sub_stick_y = 127 ;
if ( main_stick_x < - 128 )
main_stick_x = - 128 ;
if ( main_stick_y < - 128 )
main_stick_y = - 128 ;
if ( sub_stick_x < - 128 )
sub_stick_x = - 128 ;
if ( sub_stick_y < - 128 )
sub_stick_y = - 128 ;
// Send values to Dolpin
if (( main_stick_x < deadzone2 ) || ( main_stick_x > deadzone )) _pPADStatus -> stickX += main_stick_x ;
if (( main_stick_y < deadzone2 ) || ( main_stick_y > deadzone )) _pPADStatus -> stickY += main_stick_y ;
if (( sub_stick_x < deadzone2 ) || ( sub_stick_x > deadzone )) _pPADStatus -> substickX += sub_stick_x ;
if (( sub_stick_y < deadzone2 ) || ( sub_stick_y > deadzone )) _pPADStatus -> substickY += sub_stick_y ;
int triggervalue = 255 ;
if ( joystate [ _numPAD ]. halfpress )
triggervalue = 100 ;
2008-12-28 18:50:24 +00:00
int ButtonArray [] = { PAD_TRIGGER_L , PAD_TRIGGER_R ,
PAD_BUTTON_A , PAD_BUTTON_B ,
PAD_BUTTON_X , PAD_BUTTON_Y , PAD_TRIGGER_Z ,
PAD_BUTTON_START ,
PAD_BUTTON_UP , PAD_BUTTON_DOWN , PAD_BUTTON_LEFT , PAD_BUTTON_RIGHT };
for ( int a = 0 ; a <= CTL_D_PAD_RIGHT ; a ++ )
2008-12-10 03:49:17 +00:00
{
switch ( joysticks [ _numPAD ]. buttons [ a ]. c_str ()[ 0 ])
{
case 'A' :
{
// JoyNum refers to which Joystick the button is assigned to
// a is the actual button we are working with
// _numPad is the controller we are working with
int JoyNum = atoi ( joysticks [ _numPAD ]. buttons [ a ]. c_str () + 2 );
if ( joysticks [ _numPAD ]. sData [ JoyNum ]. Min == 0 )
if ( joystate [ _numPAD ]. buttons [ a ] == 0 )
continue ; // Do nothing
// We use Deadzone % to detect if we have pressed the button.
bool Pressed = false ;
if ( a == CTL_L_SHOULDER || a == CTL_R_SHOULDER || a == CTL_A_BUTTON || a == CTL_B_BUTTON )
Pressed = true ;
else
{
if ( joysticks [ _numPAD ]. buttons [ a ]. c_str ()[ 1 ] == '-' )
{
if ( joystate [ _numPAD ]. buttons [ a ] <= ( joysticks [ _numPAD ]. sData [ JoyNum ]. Min - joysticks [ _numPAD ]. sData [ JoyNum ]. Min * joysticks [ _numPAD ]. deadzone / 100.0f ))
{
Pressed = true ;
}
}
if ( joysticks [ _numPAD ]. buttons [ a ]. c_str ()[ 1 ] == '+' )
{
if ( joystate [ _numPAD ]. buttons [ a ] >= ( joysticks [ _numPAD ]. sData [ JoyNum ]. Max - joysticks [ _numPAD ]. sData [ JoyNum ]. Max * joysticks [ _numPAD ]. deadzone / 100.0f ))
{
Pressed = true ;
}
}
}
if ( Pressed == true )
{
int TriggerValue = 0 ;
2009-01-15 06:48:15 +00:00
2009-01-19 05:49:25 +00:00
2008-12-10 03:49:17 +00:00
if ( joysticks [ _numPAD ]. buttons [ a ]. c_str ()[ 1 ] == '+' )
{
if ( joystate [ _numPAD ]. buttons [ a ] >= 0 )
TriggerValue = ( 255.0f / joysticks [ _numPAD ]. sData [ JoyNum ]. Max ) * joystate [ _numPAD ]. buttons [ a ];
}
if ( joysticks [ _numPAD ]. buttons [ a ]. c_str ()[ 1 ] == '-' )
{
if ( joystate [ _numPAD ]. buttons [ a ] <= 0 )
TriggerValue = abs (( 255.0f / joysticks [ _numPAD ]. sData [ JoyNum ]. Min ) * joystate [ _numPAD ]. buttons [ a ]);
}
2009-01-19 05:49:25 +00:00
2008-12-28 18:50:24 +00:00
// Analog L and R
2008-12-10 03:49:17 +00:00
if ( a == CTL_L_SHOULDER )
{
if ( TriggerValue == 255 )
_pPADStatus -> button |= ButtonArray [ a ];
_pPADStatus -> triggerLeft = TriggerValue ;
}
2009-01-15 06:48:15 +00:00
else if ( a == CTL_R_SHOULDER )
2008-12-10 03:49:17 +00:00
{
if ( TriggerValue == 255 )
_pPADStatus -> button |= ButtonArray [ a ];
_pPADStatus -> triggerRight = TriggerValue ;
}
// TODO: Should we do the same for A and B as the L and R trigger?
else if ( a == CTL_A_BUTTON )
{
_pPADStatus -> button |= ButtonArray [ a ];
_pPADStatus -> analogA = TriggerValue ;
}
else if ( a == CTL_B_BUTTON )
{
_pPADStatus -> button |= ButtonArray [ a ];
_pPADStatus -> analogB = TriggerValue ;
}
else
_pPADStatus -> button |= ButtonArray [ a ];
}
}
break ;
case 'B' :
if ( joystate [ _numPAD ]. buttons [ a ])
{
_pPADStatus -> button |= ButtonArray [ a ];
2008-12-28 18:50:24 +00:00
// Digital L and R
2008-12-10 03:49:17 +00:00
if ( a == CTL_L_SHOULDER )
_pPADStatus -> triggerLeft = 255 ; //TODO: Do half press with these
2009-01-15 06:48:15 +00:00
else if ( a == CTL_R_SHOULDER )
2008-12-10 03:49:17 +00:00
_pPADStatus -> triggerRight = 255 ; //TODO: Half Press with these
else if ( a == CTL_A_BUTTON )
_pPADStatus -> analogA = 255 ;
else if ( a == CTL_B_BUTTON )
_pPADStatus -> analogB = 255 ;
}
case 'H' :
//PanicAlert("Hats are currently not implemented!");
default :
break ;
}
}
2008-12-08 05:25:12 +00:00
// Set buttons
2008-12-10 03:49:17 +00:00
/*if (joystate[_numPAD].buttons[CTL_L_SHOULDER])
2008-12-08 05:25:12 +00:00
{
_pPADStatus->button|=PAD_TRIGGER_L;
_pPADStatus->triggerLeft = triggervalue;
}
2009-01-15 06:48:15 +00:00
if (joystate[_numPAD].buttons[CTL_R_SHOULDER])
2008-12-08 05:25:12 +00:00
{
_pPADStatus->button|=PAD_TRIGGER_R;
_pPADStatus->triggerRight = triggervalue;
}
if (joystate[_numPAD].buttons[CTL_A_BUTTON])
{
_pPADStatus->button|=PAD_BUTTON_A;
_pPADStatus->analogA = 255; // Perhaps support pressure?
}
if (joystate[_numPAD].buttons[CTL_B_BUTTON])
{
_pPADStatus->button|=PAD_BUTTON_B;
_pPADStatus->analogB = 255; // Perhaps support pressure?
}
if (joystate[_numPAD].buttons[CTL_X_BUTTON]) _pPADStatus->button|=PAD_BUTTON_X;
if (joystate[_numPAD].buttons[CTL_Y_BUTTON]) _pPADStatus->button|=PAD_BUTTON_Y;
if (joystate[_numPAD].buttons[CTL_Z_TRIGGER]) _pPADStatus->button|=PAD_TRIGGER_Z;
2008-12-10 03:49:17 +00:00
if (joystate[_numPAD].buttons[CTL_START]) _pPADStatus->button|=PAD_BUTTON_START;*/
2008-12-08 05:25:12 +00:00
// Set D-pad
2008-12-10 03:49:17 +00:00
// TODO: Currently disabled! D:>
2008-12-08 05:25:12 +00:00
if ( joysticks [ _numPAD ]. controllertype == CTL_TYPE_JOYSTICK )
{
if ( joystate [ _numPAD ]. dpad == SDL_HAT_LEFTUP || joystate [ _numPAD ]. dpad == SDL_HAT_UP || joystate [ _numPAD ]. dpad == SDL_HAT_RIGHTUP ) _pPADStatus -> button |= PAD_BUTTON_UP ;
if ( joystate [ _numPAD ]. dpad == SDL_HAT_LEFTUP || joystate [ _numPAD ]. dpad == SDL_HAT_LEFT || joystate [ _numPAD ]. dpad == SDL_HAT_LEFTDOWN ) _pPADStatus -> button |= PAD_BUTTON_LEFT ;
if ( joystate [ _numPAD ]. dpad == SDL_HAT_LEFTDOWN || joystate [ _numPAD ]. dpad == SDL_HAT_DOWN || joystate [ _numPAD ]. dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus -> button |= PAD_BUTTON_DOWN ;
if ( joystate [ _numPAD ]. dpad == SDL_HAT_RIGHTUP || joystate [ _numPAD ]. dpad == SDL_HAT_RIGHT || joystate [ _numPAD ]. dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus -> button |= PAD_BUTTON_RIGHT ;
}
else
{
}
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
_pPADStatus -> err = PAD_ERR_NONE ;
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
#ifdef _WIN32
#ifdef USE_RUMBLE_DINPUT_HACK
if ( joystate [ _numPAD ]. halfpress )
if ( ! g_pDI )
if ( FAILED ( InitDirectInput ( m_hWnd )))
{
MessageBox ( NULL , SDL_GetError (), "Could not initialize DirectInput!" , MB_ICONERROR );
g_rumbleEnable = FALSE ;
//return;
}
else
g_rumbleEnable = TRUE ;
if ( g_rumbleEnable )
{
g_pDevice -> Acquire ();
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
if ( g_pEffect )
g_pEffect -> Start ( 1 , 0 );
}
#endif
#elif defined(__linux__)
if ( ! fd )
{
sprintf ( device_file_name , "/dev/input/event%d" , joysticks [ _numPAD ]. eventnum ); //TODO: Make dynamic //
/* Open device */
fd = open ( device_file_name , O_RDWR );
if ( fd == - 1 ) {
perror ( "Open device file" );
//Something wrong, probably permissions, just return now
return ;
}
int n_effects = 0 ;
if ( ioctl ( fd , EVIOCGEFFECTS , & n_effects ) == - 1 ) {
perror ( "Ioctl number of effects" );
}
if ( n_effects > 0 )
CanRumble = true ;
else
return ; // Return since we can't do any effects
/* a strong rumbling effect */
effect . type = FF_RUMBLE ;
effect . id = - 1 ;
effect . u . rumble . strong_magnitude = 0x8000 ;
effect . u . rumble . weak_magnitude = 0 ;
effect . replay . length = 5000 ; // Set to 5 seconds, if a Game needs more for a single rumble event, it is dumb and must be a demo
effect . replay . delay = 0 ;
if ( ioctl ( fd , EVIOCSFF , & effect ) == - 1 ) {
perror ( "Upload effect" );
CanRumble = false ; //We have effects but it doesn't support the rumble we are using. This is basic rumble, should work for most
}
}
#endif
}
// Set PAD rumble
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// (Stop=0, Rumble=1)
void PAD_Rumble ( u8 _numPAD , unsigned int _uType , unsigned int _uStrength )
{
//if(_numPAD > 0)
// return;
// not supported by SDL
// So we need to use platform specific stuff
#ifdef _WIN32
#ifdef USE_RUMBLE_DINPUT_HACK
static int a = 0 ;
if (( _uType == 0 ) || ( _uType == 2 ))
{
a = 0 ;
}
else if ( _uType == 1 )
{
a = _uStrength > 2 ? 8000 : 0 ;
}
a = int (( float ) a * 0.96f );
if ( ! g_rumbleEnable )
{
a = 0 ;
}
else
{
g_nYForce = a ;
SetDeviceForcesXY ();
}
#endif
#elif defined(__linux__)
struct input_event event ;
if ( CanRumble )
{
if ( _uType == 1 )
{
event . type = EV_FF ;
event . code = effect . id ;
event . value = 1 ;
if ( write ( fd , ( const void * ) & event , sizeof ( event )) == - 1 ) {
perror ( "Play effect" );
exit ( 1 );
}
}
if (( _uType == 0 ) || ( _uType == 2 ))
{
event . type = EV_FF ;
event . code = effect . id ;
event . value = 0 ;
if ( write ( fd , ( const void * ) & event , sizeof ( event )) == - 1 ) {
perror ( "Stop effect" );
exit ( 1 );
}
}
}
#endif
}
// Set PAD attached pads
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
unsigned int PAD_GetAttachedPads ()
{
unsigned int connected = 0 ;
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
LoadConfig ();
if ( joysticks [ 0 ]. enabled )
connected |= 1 ;
if ( joysticks [ 1 ]. enabled )
connected |= 2 ;
if ( joysticks [ 2 ]. enabled )
connected |= 4 ;
if ( joysticks [ 3 ]. enabled )
connected |= 8 ;
return connected ;
}
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// Custom Functions
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Request joystick state
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void GetJoyState ( int controller )
{
SDL_JoystickUpdate ();
for ( int a = 0 ; a < CTRL_END ; a ++ )
{
char Type = ( joysticks [ controller ]. buttons [ a ]. c_str ())[ 0 ];
//printf("Type %c, entire %s\n", Type, joysticks[controller].buttons[a].c_str());
switch ( Type )
{
case 'A' :
joystate [ controller ]. buttons [ a ] = SDL_JoystickGetAxis ( joystate [ controller ]. joy , atoi ( joysticks [ controller ]. buttons [ a ]. c_str () + 2 )); // Skip the A AND the +/- sign
break ;
case 'B' :
joystate [ controller ]. buttons [ a ] = SDL_JoystickGetButton ( joystate [ controller ]. joy , atoi ( joysticks [ controller ]. buttons [ a ]. c_str () + 1 ));
break ;
case 'H' :
printf ( "We aren't Expecting Hat here! \n " );
break ;
2009-01-10 16:23:51 +00:00
case '\0' : // When no button is being pressed
break ;
2008-12-08 05:25:12 +00:00
default :
printf ( "Unknown button type %c, number %d, Full %s \n " , Type , a , joysticks [ controller ]. buttons [ a ]. c_str ());
break ;
}
}
joystate [ controller ]. halfpress = SDL_JoystickGetButton ( joystate [ controller ]. joy , joysticks [ controller ]. halfpress );
if ( joysticks [ controller ]. controllertype == CTL_TYPE_JOYSTICK )
joystate [ controller ]. dpad = SDL_JoystickGetHat ( joystate [ controller ]. joy , joysticks [ controller ]. dpad );
else
{
}
}
// Search attached devices
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
int Search_Devices ()
{
// load config
#ifdef _DEBUG
DEBUG_INIT ();
#endif
int numjoy = SDL_NumJoysticks ();
if ( numjoy == 0 )
2009-01-23 21:28:55 +00:00
{
# ifdef _WIN32
MessageBox ( NULL , "No Joystick detected!" , NULL , MB_ICONWARNING );
#else
printf ( "No Joystick detected! \n " );
#endif
return 0 ;
2008-12-08 05:25:12 +00:00
}
if ( joyinfo )
delete [] joyinfo ;
2008-12-23 08:49:52 +00:00
joyinfo = new CONTROLLER_INFO [ numjoy ];
2008-12-08 05:25:12 +00:00
#ifdef _DEBUG
fprintf ( pFile , "Scanning for devices \n " );
fprintf ( pFile , "¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \n " );
#endif
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
for ( int i = 0 ; i < numjoy ; i ++ )
{
joyinfo [ i ]. joy = SDL_JoystickOpen ( i );
joyinfo [ i ]. ID = i ;
joyinfo [ i ]. NumAxes = SDL_JoystickNumAxes ( joyinfo [ i ]. joy );
joyinfo [ i ]. NumButtons = SDL_JoystickNumButtons ( joyinfo [ i ]. joy );
joyinfo [ i ]. NumBalls = SDL_JoystickNumBalls ( joyinfo [ i ]. joy );
joyinfo [ i ]. NumHats = SDL_JoystickNumHats ( joyinfo [ i ]. joy );
joyinfo [ i ]. Name = SDL_JoystickName ( i );
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
printf ( "ID: %d \n " , i );
printf ( "Name: %s \n " , joyinfo [ i ]. Name );
printf ( "Buttons: %d \n " , joyinfo [ i ]. NumButtons );
printf ( "Axises: %d \n " , joyinfo [ i ]. NumAxes );
printf ( "Hats: %d \n " , joyinfo [ i ]. NumHats );
printf ( "Balls: %d \n\n " , joyinfo [ i ]. NumBalls );
// Close if opened
if ( SDL_JoystickOpened ( i ))
SDL_JoystickClose ( joyinfo [ i ]. joy );
}
return numjoy ;
}
// Enable output log
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void DEBUG_INIT ()
{
if ( pFile )
return ;
#ifdef _WIN32
2009-01-15 06:48:15 +00:00
char dateStr [ 9 ];
2008-12-08 05:25:12 +00:00
_strdate ( dateStr );
2009-01-15 06:48:15 +00:00
char timeStr [ 9 ];
2008-12-08 05:25:12 +00:00
_strtime ( timeStr );
#endif
pFile = fopen ( "nJoy-debug.txt" , "wt" );
fprintf ( pFile , "nJoy v" INPUT_VERSION " Debug \n " );
#ifdef _WIN32
fprintf ( pFile , "Date: %s \n Time: %s \n " , dateStr , timeStr );
#endif
fprintf ( pFile , "¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \n " );
}
// Disable output log
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void DEBUG_QUIT ()
{
if ( ! pFile )
return ;
#ifdef _WIN32
2009-01-15 06:48:15 +00:00
char timeStr [ 9 ];
2008-12-08 05:25:12 +00:00
_strtime ( timeStr );
fprintf ( pFile , "_______________ \n " );
fprintf ( pFile , "Time: %s" , timeStr );
#endif
fclose ( pFile );
}
// Save settings to file
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void SaveConfig ()
{
IniFile file ;
file . Load ( "nJoy.ini" );
for ( int i = 0 ; i < 4 ; i ++ )
{
char SectionName [ 32 ];
sprintf ( SectionName , "PAD%i" , i + 1 );
file . Set ( SectionName , "l_shoulder" , joysticks [ i ]. buttons [ CTL_L_SHOULDER ]);
file . Set ( SectionName , "r_shoulder" , joysticks [ i ]. buttons [ CTL_R_SHOULDER ]);
file . Set ( SectionName , "a_button" , joysticks [ i ]. buttons [ CTL_A_BUTTON ]);
file . Set ( SectionName , "b_button" , joysticks [ i ]. buttons [ CTL_B_BUTTON ]);
file . Set ( SectionName , "x_button" , joysticks [ i ]. buttons [ CTL_X_BUTTON ]);
file . Set ( SectionName , "y_button" , joysticks [ i ]. buttons [ CTL_Y_BUTTON ]);
file . Set ( SectionName , "z_trigger" , joysticks [ i ]. buttons [ CTL_Z_TRIGGER ]);
file . Set ( SectionName , "start_button" , joysticks [ i ]. buttons [ CTL_START ]);
2009-01-15 06:48:15 +00:00
file . Set ( SectionName , "dpad" , joysticks [ i ]. dpad );
2008-12-10 03:49:17 +00:00
file . Set ( SectionName , "dpad_up" , joysticks [ i ]. buttons [ CTL_D_PAD_UP ]);
file . Set ( SectionName , "dpad_down" , joysticks [ i ]. buttons [ CTL_D_PAD_DOWN ]);
file . Set ( SectionName , "dpad_left" , joysticks [ i ]. buttons [ CTL_D_PAD_LEFT ]);
file . Set ( SectionName , "dpad_right" , joysticks [ i ]. buttons [ CTL_D_PAD_RIGHT ]);
2008-12-08 05:25:12 +00:00
file . Set ( SectionName , "main_x" , joysticks [ i ]. buttons [ CTL_MAIN_X ]);
file . Set ( SectionName , "main_y" , joysticks [ i ]. buttons [ CTL_MAIN_Y ]);
file . Set ( SectionName , "sub_x" , joysticks [ i ]. buttons [ CTL_SUB_X ]);
file . Set ( SectionName , "sub_y" , joysticks [ i ]. buttons [ CTL_SUB_Y ]);
file . Set ( SectionName , "enabled" , joysticks [ i ]. enabled );
file . Set ( SectionName , "deadzone" , joysticks [ i ]. deadzone );
file . Set ( SectionName , "halfpress" , joysticks [ i ]. halfpress );
file . Set ( SectionName , "joy_id" , joysticks [ i ]. ID );
file . Set ( SectionName , "controllertype" , joysticks [ i ]. controllertype );
file . Set ( SectionName , "eventnum" , joysticks [ i ]. eventnum );
for ( int a = 0 ; a < MAX_AXISES ; a ++ )
{
char Section [ 32 ];
sprintf ( Section , "SAxis%dMin" , a );
file . Set ( SectionName , Section , ( int ) joysticks [ i ]. sData [ a ]. Min );
sprintf ( Section , "SAxis%dMax" , a );
file . Set ( SectionName , Section , ( int ) joysticks [ i ]. sData [ a ]. Max );
}
}
file . Save ( "nJoy.ini" );
}
// Load settings from file
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void LoadConfig ()
{
IniFile file ;
file . Load ( "nJoy.ini" );
for ( int i = 0 ; i < 4 ; i ++ )
{
char SectionName [ 32 ];
sprintf ( SectionName , "PAD%i" , i + 1 );
file . Get ( SectionName , "l_shoulder" , & joysticks [ i ]. buttons [ CTL_L_SHOULDER ], "B4" );
file . Get ( SectionName , "r_shoulder" , & joysticks [ i ]. buttons [ CTL_R_SHOULDER ], "B5" );
file . Get ( SectionName , "a_button" , & joysticks [ i ]. buttons [ CTL_A_BUTTON ], "B0" );
2009-01-15 06:48:15 +00:00
file . Get ( SectionName , "b_button" , & joysticks [ i ]. buttons [ CTL_B_BUTTON ], "B1" );
2008-12-08 05:25:12 +00:00
file . Get ( SectionName , "x_button" , & joysticks [ i ]. buttons [ CTL_X_BUTTON ], "B3" );
2009-01-15 06:48:15 +00:00
file . Get ( SectionName , "y_button" , & joysticks [ i ]. buttons [ CTL_Y_BUTTON ], "B2" );
2008-12-08 05:25:12 +00:00
file . Get ( SectionName , "z_trigger" , & joysticks [ i ]. buttons [ CTL_Z_TRIGGER ], "B7" );
2009-01-15 06:48:15 +00:00
file . Get ( SectionName , "start_button" , & joysticks [ i ]. buttons [ CTL_START ], "B9" );
file . Get ( SectionName , "dpad" , & joysticks [ i ]. dpad , 0 );
2008-12-10 03:49:17 +00:00
file . Get ( SectionName , "dpad_up" , & joysticks [ i ]. buttons [ CTL_D_PAD_UP ], 0 );
file . Get ( SectionName , "dpad_down" , & joysticks [ i ]. buttons [ CTL_D_PAD_DOWN ], 0 );
file . Get ( SectionName , "dpad_left" , & joysticks [ i ]. buttons [ CTL_D_PAD_LEFT ], 0 );
file . Get ( SectionName , "dpad_right" , & joysticks [ i ]. buttons [ CTL_D_PAD_RIGHT ], 0 );
2009-01-15 06:48:15 +00:00
file . Get ( SectionName , "main_x" , & joysticks [ i ]. buttons [ CTL_MAIN_X ], "A0" );
file . Get ( SectionName , "main_y" , & joysticks [ i ]. buttons [ CTL_MAIN_Y ], "A1" );
file . Get ( SectionName , "sub_x" , & joysticks [ i ]. buttons [ CTL_SUB_X ], "A2" );
file . Get ( SectionName , "sub_y" , & joysticks [ i ]. buttons [ CTL_SUB_Y ], "A3" );
file . Get ( SectionName , "enabled" , & joysticks [ i ]. enabled , 1 );
file . Get ( SectionName , "deadzone" , & joysticks [ i ]. deadzone , 9 );
file . Get ( SectionName , "halfpress" , & joysticks [ i ]. halfpress , 6 );
2008-12-08 05:25:12 +00:00
file . Get ( SectionName , "joy_id" , & joysticks [ i ]. ID , 0 );
file . Get ( SectionName , "controllertype" , & joysticks [ i ]. controllertype , 0 );
file . Get ( SectionName , "eventnum" , & joysticks [ i ]. eventnum , 0 );
for ( int a = 0 ; a < MAX_AXISES ; a ++ )
{
char Section [ 32 ];
int Min ;
int Max ;
sprintf ( Section , "SAxis%dMin" , a );
file . Get ( SectionName , Section , & Min , 0 );
sprintf ( Section , "SAxis%dMax" , a );
file . Get ( SectionName , Section , & Max , 0 );
joysticks [ i ]. sData [ a ]. Min = Min ;
joysticks [ i ]. sData [ a ]. Max = Max ;
}
}
}
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
#ifdef _WIN32
//////////////////////////////////////////////////////////////////////////////////////////
// Rumble stuff :D!
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//
#ifdef USE_RUMBLE_DINPUT_HACK
HRESULT InitDirectInput ( HWND hDlg )
{
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_pDI , NULL )))
{
return hr ;
}
// Look for a force feedback device we can use
if ( FAILED ( hr = g_pDI -> EnumDevices ( DI8DEVCLASS_GAMECTRL , EnumFFDevicesCallback , NULL , DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK )))
{
return hr ;
}
if ( NULL == g_pDevice )
{
MessageBox ( NULL , "Force feedback device not found. nJoy will now disable rumble." , "FFConst" , MB_ICONERROR | MB_OK );
g_rumbleEnable = FALSE ;
2009-01-15 06:48:15 +00:00
2008-12-08 05:25:12 +00:00
return S_OK ;
}
// Set the data format to "simple joystick" - a predefined data format. A
// data format specifies which controls on a device we are interested in,
// and how they should be reported.
//
// This tells DirectInput that we will be passing a DIJOYSTATE structure to
// IDirectInputDevice8::GetDeviceState(). Even though we won't actually do
// it in this sample. But setting the data format is important so that the
// DIJOFS_* values work properly.
if ( FAILED ( hr = g_pDevice -> SetDataFormat ( & c_dfDIJoystick )))
return hr ;
// Set the cooperative level to let DInput know how this device should
// interact with the system and with other DInput applications.
// Exclusive access is required in order to perform force feedback.
//if(FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
2009-01-15 06:48:15 +00:00
if ( FAILED ( hr = g_pDevice -> SetCooperativeLevel ( hDlg , DISCL_EXCLUSIVE | DISCL_FOREGROUND )))
2008-12-08 05:25:12 +00:00
{
return hr ;
}
// Since we will be playing force feedback effects, we should disable the
// auto-centering spring.
dipdw . diph . dwSize = sizeof ( DIPROPDWORD );
dipdw . diph . dwHeaderSize = sizeof ( DIPROPHEADER );
dipdw . diph . dwObj = 0 ;
dipdw . diph . dwHow = DIPH_DEVICE ;
dipdw . dwData = FALSE ;
if ( FAILED ( hr = g_pDevice -> SetProperty ( DIPROP_AUTOCENTER , & dipdw . diph )))
return hr ;
2009-01-15 06:48:15 +00:00
// Enumerate and count the axes of the joystick
2008-12-08 05:25:12 +00:00
if ( FAILED ( hr = g_pDevice -> EnumObjects ( EnumAxesCallback , ( VOID * ) & g_dwNumForceFeedbackAxis , DIDFT_AXIS )))
return hr ;
// This simple sample only supports one or two axis joysticks
if ( g_dwNumForceFeedbackAxis > 2 )
g_dwNumForceFeedbackAxis = 2 ;
// This application needs only one effect: Applying raw forces.
DWORD rgdwAxes [ 2 ] = { DIJOFS_X , DIJOFS_Y };
LONG rglDirection [ 2 ] = { 0 , 0 };
DICONSTANTFORCE cf = { 0 };
DIEFFECT eff ;
ZeroMemory ( & eff , sizeof ( eff ));
eff . dwSize = sizeof ( DIEFFECT );
eff . dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS ;
eff . dwDuration = INFINITE ;
eff . dwSamplePeriod = 0 ;
eff . dwGain = DI_FFNOMINALMAX ;
eff . dwTriggerButton = DIEB_NOTRIGGER ;
eff . dwTriggerRepeatInterval = 0 ;
eff . cAxes = g_dwNumForceFeedbackAxis ;
eff . rgdwAxes = rgdwAxes ;
eff . rglDirection = rglDirection ;
eff . lpEnvelope = 0 ;
eff . cbTypeSpecificParams = sizeof ( DICONSTANTFORCE );
eff . lpvTypeSpecificParams = & cf ;
eff . dwStartDelay = 0 ;
// Create the prepared effect
if ( FAILED ( hr = g_pDevice -> CreateEffect ( GUID_ConstantForce , & eff , & g_pEffect , NULL )))
{
return hr ;
}
if ( NULL == g_pEffect )
return E_FAIL ;
return S_OK ;
}
VOID FreeDirectInput ()
{
2009-01-15 06:48:15 +00:00
// Unacquire the device one last time just in case
2008-12-08 05:25:12 +00:00
// the app tried to exit while the device is still acquired.
if ( g_pDevice )
g_pDevice -> Unacquire ();
// Release any DirectInput objects.
SAFE_RELEASE ( g_pEffect );
SAFE_RELEASE ( g_pDevice );
SAFE_RELEASE ( g_pDI );
}
2008-12-12 17:36:12 +00:00
BOOL CALLBACK EnumFFDevicesCallback ( const DIDEVICEINSTANCE * pInst , VOID * pContext )
2008-12-08 05:25:12 +00:00
{
LPDIRECTINPUTDEVICE8 pDevice ;
HRESULT hr ;
// Obtain an interface to the enumerated force feedback device.
hr = g_pDI -> CreateDevice ( pInst -> guidInstance , & pDevice , NULL );
// If it failed, then we can't use this device for some bizarre reason.
// (Maybe the user unplugged it while we were in the middle of enumerating it.) So continue enumerating
if ( FAILED ( hr ))
return DIENUM_CONTINUE ;
// We successfully created an IDirectInputDevice8. So stop looking for another one.
g_pDevice = pDevice ;
return DIENUM_STOP ;
}
2008-12-12 17:36:12 +00:00
BOOL CALLBACK EnumAxesCallback ( const DIDEVICEOBJECTINSTANCE * pdidoi , VOID * pContext )
2008-12-08 05:25:12 +00:00
{
DWORD * pdwNumForceFeedbackAxis = ( DWORD * ) pContext ;
if (( pdidoi -> dwFlags & DIDOI_FFACTUATOR ) != 0 )
( * pdwNumForceFeedbackAxis ) ++ ;
return DIENUM_CONTINUE ;
}
HRESULT SetDeviceForcesXY ()
{
// Modifying an effect is basically the same as creating a new one, except you need only specify the parameters you are modifying
LONG rglDirection [ 2 ] = { 0 , 0 };
DICONSTANTFORCE cf ;
if ( g_dwNumForceFeedbackAxis == 1 )
{
// If only one force feedback axis, then apply only one direction and keep the direction at zero
cf . lMagnitude = g_nXForce ;
rglDirection [ 0 ] = 0 ;
}
else
{
2009-01-15 06:48:15 +00:00
// If two force feedback axis, then apply magnitude from both directions
2008-12-08 05:25:12 +00:00
rglDirection [ 0 ] = g_nXForce ;
rglDirection [ 1 ] = g_nYForce ;
cf . lMagnitude = ( DWORD ) sqrt (( double ) g_nXForce * ( double ) g_nXForce + ( double ) g_nYForce * ( double ) g_nYForce );
}
DIEFFECT eff ;
ZeroMemory ( & eff , sizeof ( eff ));
eff . dwSize = sizeof ( DIEFFECT );
eff . dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS ;
eff . cAxes = g_dwNumForceFeedbackAxis ;
eff . rglDirection = rglDirection ;
eff . lpEnvelope = 0 ;
eff . cbTypeSpecificParams = sizeof ( DICONSTANTFORCE );
eff . lpvTypeSpecificParams = & cf ;
eff . dwStartDelay = 0 ;
// Now set the new parameters and start the effect immediately.
return g_pEffect -> SetParameters ( & eff , DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START );
}
#endif
#endif