2008-12-08 05:25:12 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// Project description
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
// Name: nJoy
// 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
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
FILE * pFile ;
CONTROLLER_INFO * joyinfo = 0 ;
CONTROLLER_STATE joystate [ 4 ] ;
CONTROLLER_MAPPING joysticks [ 4 ] ;
bool emulator_running = FALSE ;
2008-12-22 10:47:37 +00:00
// TODO: fix this dirty hack to stop missing symbols
void __Log ( int log , const char * format , . . . ) { }
void __Logv ( int log , int v , const char * format , . . . ) { }
2008-12-08 05:25:12 +00:00
// Handle to window
HWND m_hWnd ;
# ifdef USE_RUMBLE_DINPUT_HACK
bool g_rumbleEnable = FALSE ;
# endif
// 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
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
class wxDLLApp : public wxApp
{
bool OnInit ( )
{
return true ;
}
} ;
IMPLEMENT_APP_NO_MAIN ( wxDLLApp )
WXDLLIMPEXP_BASE void wxSetInstance ( HINSTANCE hInst ) ;
2009-01-05 22:11:08 +00:00
# endif
2008-12-08 05:25:12 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// DllMain
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
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
{
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
}
break ;
case DLL_PROCESS_DETACH :
2009-01-05 22:11:08 +00:00
# if defined(HAVE_WX) && HAVE_WX
2008-12-08 05:25:12 +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 ;
}
nJoy_hInst = hinstDLL ;
return TRUE ;
}
# endif
//////////////////////////////////////////////////////////////////////////////////////////
// Input Plugin Functions (from spec's)
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
// Get properties of plugin
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
void GetDllInfo ( PLUGIN_INFO * _PluginInfo )
{
_PluginInfo - > Version = 0x0100 ;
_PluginInfo - > Type = PLUGIN_TYPE_PAD ;
# ifdef DEBUGFAST
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-01-08 12:12:15 +00:00
void SetDllGlobals ( PLUGIN_GLOBALS * _pPluginGlobals ) {
}
2008-12-08 05:25:12 +00:00
// Call config dialog
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
void DllConfig ( HWND _hParent )
{
# ifdef _WIN32
if ( SDL_Init ( SDL_INIT_JOYSTICK ) < 0 )
{
MessageBox ( NULL , SDL_GetError ( ) , " Could not initialize SDL! " , MB_ICONERROR ) ;
return ;
}
LoadConfig ( ) ; // load settings
2008-12-02 01:08:21 +00:00
2009-01-05 22:11:08 +00:00
# if defined(HAVE_WX) && HAVE_WX
2008-12-02 01:08:21 +00:00
wxWindow win ;
win . SetHWND ( _hParent ) ;
ConfigBox frame ( & win ) ;
frame . ShowModal ( ) ;
2008-12-08 05:25:12 +00:00
win . SetHWND ( 0 ) ;
2009-01-05 22:11:08 +00:00
# endif
2008-12-08 05:25:12 +00:00
# else
if ( SDL_Init ( SDL_INIT_JOYSTICK ) < 0 )
{
printf ( " Could not initialize SDL! (%s) \n " , SDL_GetError ( ) ) ;
return ;
}
LoadConfig ( ) ; // load settings
2009-01-05 22:11:08 +00:00
# if defined(HAVE_WX) && HAVE_WX
2008-12-08 05:25:12 +00:00
ConfigBox frame ( NULL ) ;
frame . ShowModal ( ) ;
2009-01-05 22:11:08 +00:00
# endif
2008-12-08 05:25:12 +00:00
# endif
}
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)
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
void PAD_Initialize ( SPADInitialize _PADInitialize )
{
emulator_running = TRUE ;
# ifdef _DEBUG
DEBUG_INIT ( ) ;
# endif
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 ;
}
# ifdef _WIN32
m_hWnd = ( HWND ) _PADInitialize . hWnd ;
# endif
LoadConfig ( ) ; // Load joystick mapping
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)
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
void PAD_Shutdown ( )
{
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
delete [ ] joyinfo ;
emulator_running = FALSE ;
# ifdef _WIN32
# ifdef USE_RUMBLE_DINPUT_HACK
FreeDirectInput ( ) ;
# endif
# elif defined(__linux__)
close ( fd ) ;
# endif
}
2008-12-28 18:50:24 +00:00
// Set buttons status from wxWidgets in the main application
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
void PAD_Input ( u8 _Key , u8 _UpDown ) { }
2008-12-08 05:25:12 +00:00
// Set PAD status
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
void PAD_GetStatus ( u8 _numPAD , SPADStatus * _pPADStatus )
{
if ( ! joysticks [ _numPAD ] . enabled )
return ;
// clear pad status
memset ( _pPADStatus , 0 , sizeof ( SPADStatus ) ) ;
// get pad status
GetJoyState ( _numPAD ) ;
// 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
// 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 ;
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 ] ) ;
}
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 ;
}
else if ( a = = CTL_R_SHOULDER )
{
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
else if ( a = = CTL_R_SHOULDER )
_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 ;
}
if ( joystate [ _numPAD ] . buttons [ CTL_R_SHOULDER ] )
{
_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
{
}
_pPADStatus - > err = PAD_ERR_NONE ;
# 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 ( ) ;
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
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
// (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
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
unsigned int PAD_GetAttachedPads ( )
{
unsigned int connected = 0 ;
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 ;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Custom Functions
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
// Request joystick state
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
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 ;
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
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
int Search_Devices ( )
{
// load config
# ifdef _DEBUG
DEBUG_INIT ( ) ;
# endif
int numjoy = SDL_NumJoysticks ( ) ;
if ( numjoy = = 0 )
{
# ifdef _WIN32
MessageBox ( NULL , " No Joystick detected! " , NULL , MB_ICONWARNING ) ;
# else
printf ( " No Joystick detected! \n " ) ;
# endif
return 0 ;
}
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 , " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> \n " ) ;
# endif
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 ) ;
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
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
void DEBUG_INIT ( )
{
if ( pFile )
return ;
# ifdef _WIN32
char dateStr [ 9 ] ;
_strdate ( dateStr ) ;
char timeStr [ 9 ] ;
_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 , " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> \n " ) ;
}
// Disable output log
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
void DEBUG_QUIT ( )
{
if ( ! pFile )
return ;
# ifdef _WIN32
char timeStr [ 9 ] ;
_strtime ( timeStr ) ;
fprintf ( pFile , " _______________ \n " ) ;
fprintf ( pFile , " Time: %s " , timeStr ) ;
# endif
fclose ( pFile ) ;
}
// Save settings to file
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
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 ] ) ;
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
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
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 " ) ;
file . Get ( SectionName , " b_button " , & joysticks [ i ] . buttons [ CTL_B_BUTTON ] , " B1 " ) ;
file . Get ( SectionName , " x_button " , & joysticks [ i ] . buttons [ CTL_X_BUTTON ] , " B3 " ) ;
file . Get ( SectionName , " y_button " , & joysticks [ i ] . buttons [ CTL_Y_BUTTON ] , " B2 " ) ;
file . Get ( SectionName , " z_trigger " , & joysticks [ i ] . buttons [ CTL_Z_TRIGGER ] , " B7 " ) ;
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 ) ;
2008-12-08 05:25:12 +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 ) ;
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 ;
}
}
}
# ifdef _WIN32
//////////////////////////////////////////////////////////////////////////////////////////
// Rumble stuff :D!
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
//
# 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 ;
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)))
if ( FAILED ( hr = g_pDevice - > SetCooperativeLevel ( hDlg , DISCL_EXCLUSIVE | DISCL_FOREGROUND ) ) )
{
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 ;
// Enumerate and count the axes of the joystick
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 ( )
{
// Unacquire the device one last time just in case
// 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
{
// If two force feedback axis, then apply magnitude from both directions
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