Jump to content
  • Advertisement
Sign in to follow this  
Anders2

DirectInput EnumDevicesBySemantics call fail

This topic is 3994 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all! As a DirectX newbie I've trying to get DirectInput actionmapping working. My code fails at the EnumDevicesBySemantics call returning E_INVALIDARG. After checking with other source code, MS and running in debug mode to check the values I still can't pinpoint where the error is. I hope anyone here can guide me in the right direction... First the header file:
// This header file sets different values returned by the input functions.

// The guidActionMap is a unique GUID for every application. This one is
// generated from within Visual Studio using Tools | Create GUID. Select
// static const struct GUID and generate. This GUID is unique, so create a new
// one if copying/pasting this code to another application.

// {8E38161D-F56C-4f9f-96E1-68D53EA54CCA}
static const GUID ACTIONMAP_GUID = 
{ 0x8e38161d, 0xf56c, 0x4f9f, { 0x96, 0xe1, 0x68, 0xd5, 0x3e, 0xa5, 0x4c, 0xca } };


// Below are different game actions defined. They define the different actions the
// player can take. These actions are later mapped using action mapping.

#define INPUT_XAXIS              1L             //Movement in the X axis
#define INPUT_LEFT               2L             //Move left
#define INPUT_RIGHT              3L             //Move right
#define INPUT_YAXIS              4L             //Movement in the Y axis
#define INPUT_UP                 5L             //Move up
#define INPUT_DOWN               6L             //Move down
#define INPUT_SHOOT              7L             //Well, guess what...
#define INPUT_SELECT             8L             //Used for something?
//#define INPUT_SHIELD             9L             //Activate shields
#define INPUT_JUMP               10L            //Jumping...
#define INPUT_BOOST              11L            //Speed up!

#define INPUT_PAUSE              12L            //Pause game
#define INPUT_MUTE               13L            //Mute sound/music
#define INPUT_SOUNDUP            14L            //Raise volume
#define INPUT_SOUNDDOWN          15L            //Lower volume
#define INPUT_QUIT               16L            //Quit game

#define INPUT_NACTIONS           25L            //Number of defined actions in action map
#define DI_BUFSIZE               16             //Directinput input buffer size
#define DI_MAXDEVICES            10             //Maximum number of detected DirectInput devices

LPDIRECTINPUT8 gp_DI=NULL;                      //Pointer to DirectInput object
LPDIRECTINPUTDEVICE8 g_lpDevices[DI_MAXDEVICES]; //Array of pointers to enumerated devices
int g_iDevices=0;                               //Holds numer of enumerated devices for array

static DIACTIONFORMAT g_ActionFormat;           //Structure with genre, buffer size axis scaling etc

// The data below sets up the action map for DirectInput. Each game action is
// assigned to at least one virtual control or device object. The controls are defined
// as action-mapping constants and are defined by genre and sub-genre.

DIACTION g_GameAction [INPUT_NACTIONS]=
{
   // Assign actions with controls, these are set up by DirectInput

   { INPUT_XAXIS, DIAXIS_ARCADEP_LATERAL, 0, (LPCSTR)"Left/Right", }, 
   { INPUT_YAXIS, DIAXIS_ARCADEP_MOVE, 0, (LPCSTR)"Up/Down", },
   { INPUT_SHOOT, DIBUTTON_ARCADEP_FIRE, 0, (LPCSTR)"Shoot", },
   { INPUT_SELECT, DIBUTTON_ARCADEP_SELECT, 0, (LPCSTR)"Select", },
   { INPUT_JUMP, DIBUTTON_ARCADEP_JUMP, 0, (LPCSTR)"Jump", },
   { INPUT_BOOST, DIBUTTON_ARCADEP_FIRESECONDARY, 0, (LPCSTR)"Boost", },
   { INPUT_PAUSE, DIBUTTON_ARCADEP_PAUSE, 0, (LPCSTR)"Pause Game", },
   { INPUT_QUIT, DIBUTTON_ARCADEP_MENU, 0, (LPCSTR)"Quit Game", },
   
   // Assign actions for keyboard

   { INPUT_LEFT, DIK_LEFT, 0, (LPCSTR)"Left", },
   { INPUT_RIGHT, DIK_RIGHT, 0, (LPCSTR)"Right", },
   { INPUT_UP, DIK_UP, 0, (LPCSTR)"Up", },
   { INPUT_DOWN, DIK_DOWN, 0, (LPCSTR)"Down", },
   { INPUT_SHOOT, DIK_F, 0, (LPCSTR)"Shoot", },
   { INPUT_JUMP, DIK_J, 0, (LPCSTR)"Jump", },
   { INPUT_BOOST, DIK_B, 0, (LPCSTR)"Boost", },
   { INPUT_SELECT, DIK_S, 0, (LPCSTR)"Select", },
   { INPUT_PAUSE, DIK_SPACE, 0, (LPCSTR)"Pause Game", },
   { INPUT_MUTE,DIK_MUTE, 0, (LPCSTR)"Mute Sound", },
   { INPUT_SOUNDUP,DIK_VOLUMEUP, 0, (LPCSTR)"Increase Volume", },
   { INPUT_SOUNDDOWN,DIK_VOLUMEDOWN, 0, (LPCSTR)"Decrease Volume", },
   { INPUT_QUIT, DIK_ESCAPE, 0, (LPCSTR)"Quit Game", },

   // Assign actions for mouse
   
   { INPUT_XAXIS, DIMOUSE_XAXIS, 0, (LPCSTR)"Left/Right", },
   { INPUT_YAXIS, DIMOUSE_YAXIS, 0, (LPCSTR)"Up/Down", },
   { INPUT_SHOOT, DIMOUSE_BUTTON0, 0, (LPCSTR)"Shoot", },
   { INPUT_JUMP, DIMOUSE_BUTTON1, 0, (LPCSTR)"Jump", }, 

};
and after the header some code:
HRESULT hr;                                     //Result returned from calls

hr=DirectInput8Create                           //Get DirectInput pointer interface
   (GetModuleHandle (NULL),                     //Module handle for this application
   DIRECTINPUT_VERSION,                         //Version of DirectInput application designed for
   IID_IDirectInput8A,                          //Use ANSI version of the interface
   (VOID**)&gp_DI,                              //Address of ptr to receive interface ptr
   NULL);                                       //Do not use COM aggregated interface

if (FAILED (hr)) AppError (26,hr);              //If failed to create DirectInput interface pointer

ZeroMemory (&g_ActionFormat, sizeof (DIACTIONFORMAT)); //Clear the structure first

g_ActionFormat.dwSize=sizeof (DIACTIONFORMAT);  //Size of structure
g_ActionFormat.dwActionSize=sizeof (DIACTION);  //Size of action structure

// Calculate size of action map and number of entries

g_ActionFormat.dwDataSize=INPUT_NACTIONS * sizeof (DWORD);
g_ActionFormat.dwNumActions=INPUT_NACTIONS;

// The guidActionMap is a unique GUID for every application. This one is
// generated from within Visual Studio using Tools | Create GUID. Select
// static const struct GUID and generate. This GUID is unique, so create a new
// one if copying/pasting this code to another application.

g_ActionFormat.guidActionMap=ACTIONMAP_GUID; //Setting GUID for the actionmap

g_ActionFormat.dwGenre=DIVIRTUAL_ARCADE_PLATFORM; //Set genre
g_ActionFormat.rgoAction=g_GameAction;          //Array with actions
g_ActionFormat.dwBufferSize=DI_BUFSIZE;         //Size of input buffer
g_ActionFormat.lAxisMax=100;                    //Axis max value
g_ActionFormat.lAxisMin=-100;                   //Axis min value
strcpy_s (g_ActionFormat.tszActionMap,"Game Controls\0"); //Friendly name of action map
g_ActionFormat.hInstString=NULL;                //String action names are defined with actions

hr=gp_DI->EnumDevicesBySemantics                //Apply the mappings to physical devices
   (NULL,                                       //User string name, NULL=login name
   &g_ActionFormat,                             //Adress to ActionFormat structure
   Input_EnumDevicesCallback,                   //Callback function for each found device
   NULL,                                        //Value to send to callback function
   DIEDBSFL_ATTACHEDONLY);                      //Scan attached and installed devices only

if (FAILED (hr)) AppError (27,hr);              //Call error function if failed
And that's pretty much it. My application fails calling the AppError above. /Anders EDIT: Please remember 'source' tags in future.

Share this post


Link to post
Share on other sites
Advertisement
Oh, noticed that I forgot to post the callback!
Here it is:

// The callback function below receives DirectInput devices when they are enumerated with the
// EnumDevicesBySemantics call. It tries to map applicable actions to the found object and
// returns continue code if more devices are left to enumerate.

BOOL CALLBACK Input_EnumDevicesCallback //Callback function that receive DirectInput devices
(LPCDIDEVICEINSTANCE lpddi, //Adress of structure describing device instance
LPDIRECTINPUTDEVICE8 lpdid, //Pointer to device interface
DWORD dwFlags, //Flags telling why being enumerated
DWORD dwRemaining, //Number of devices remaining to be enumerated
LPVOID pvRef) //Application defined value. Always NULL here
{
HRESULT hr; //Result returned from calls

if (lpdid!=NULL) //Check for valid pointer first
{
hr=lpdid->SetCooperativeLevel //Assign exclusive control of this device
(Init.hwnd, //Top level window
DISCL_EXCLUSIVE | DISCL_FOREGROUND); //Require exclusive foreground access

if (FAILED (hr)) return (DIENUM_CONTINUE); //Continue enumeration if failure

hr=lpdid->BuildActionMap (&g_ActionFormat, //Map applicable actions to current object
NULL, //User string name, NULL=login name
DIDBAM_DEFAULT); //Overwrite mappings except application-specified mappings

if (FAILED (hr)) return (DIENUM_CONTINUE); //AppError (29,hr); //Call error function if failure

if (g_iDevices>DI_MAXDEVICES-1) //If maximum enumerated deices reached
return (DIENUM_STOP); //Stop enumerating devices

g_lpDevices[g_iDevices]=lpdid; //Store device interface into array

hr=g_lpDevices[g_iDevices]->SetActionMap //Apply map configuration to devices
(&g_ActionFormat, //Adress to ActionFormat structure
NULL, //User string name, NULL=login name
DIDSAM_DEFAULT); //Set action map for this user, save it if differs

if (FAILED (hr)) return (DIENUM_CONTINUE); //AppError (28,hr); //Call error function if failed

lpdid->AddRef(); //Add a reference to this device
g_iDevices++; //Increase number of enumerated devices

// if (g_iDevices>DI_MAXDEVICES-1) //If maximum enumerated deices reached
// AppError (30,0); //Call error function
}

// If there still are devices to enumerate return continue code,
// else send stop code.

return (dwRemaining ? DIENUM_CONTINUE:DIENUM_STOP);
}

Share this post


Link to post
Share on other sites
Reposting the callback with source tags, they were added automatically earlier:



// The callback function below receives DirectInput devices when they are enumerated with the
// EnumDevicesBySemantics call. It tries to map applicable actions to the found object and
// returns continue code if more devices are left to enumerate.

BOOL CALLBACK Input_EnumDevicesCallback //Callback function that receive DirectInput devices
(LPCDIDEVICEINSTANCE lpddi, //Adress of structure describing device instance
LPDIRECTINPUTDEVICE8 lpdid, //Pointer to device interface
DWORD dwFlags, //Flags telling why being enumerated
DWORD dwRemaining, //Number of devices remaining to be enumerated
LPVOID pvRef) //Application defined value. Always NULL here
{
HRESULT hr; //Result returned from calls

if (lpdid!=NULL) //Check for valid pointer first
{
hr=lpdid->SetCooperativeLevel //Assign exclusive control of this device
(Init.hwnd, //Top level window
DISCL_EXCLUSIVE | DISCL_FOREGROUND); //Require exclusive foreground access

if (FAILED (hr)) return (DIENUM_CONTINUE); //Continue enumeration if failure

hr=lpdid->BuildActionMap (&g_ActionFormat, //Map applicable actions to current object
NULL, //User string name, NULL=login name
DIDBAM_DEFAULT); //Overwrite mappings except application-specified mappings

if (FAILED (hr)) return (DIENUM_CONTINUE); //AppError (29,hr); //Call error function if failure

if (g_iDevices>DI_MAXDEVICES-1) //If maximum enumerated deices reached
return (DIENUM_STOP); //Stop enumerating devices

g_lpDevices[g_iDevices]=lpdid; //Store device interface into array

hr=g_lpDevices[g_iDevices]->SetActionMap //Apply map configuration to devices
(&g_ActionFormat, //Adress to ActionFormat structure
NULL, //User string name, NULL=login name
DIDSAM_DEFAULT); //Set action map for this user, save it if differs

if (FAILED (hr)) return (DIENUM_CONTINUE); //AppError (28,hr); //Call error function if failed

lpdid->AddRef(); //Add a reference to this device
g_iDevices++; //Increase number of enumerated devices

// if (g_iDevices>DI_MAXDEVICES-1) //If maximum enumerated deices reached
// AppError (30,0); //Call error function
}

// If there still are devices to enumerate return continue code,
// else send stop code.

return (dwRemaining ? DIENUM_CONTINUE:DIENUM_STOP);
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!