int Game_Init(void *parms,  int num_parms)
{
// this function is where you do all the initialization 
// for your game

int index;         // looping var
char filename[80]; // used to build up files names

// initialize directdraw
DDraw_Init(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP);

// first create the direct input object
DirectInput8Create(main_instance,DIRECTINPUT_VERSION,IID_IDirectInput8, (void **)&lpdi,NULL);

// create a mouse device  /////////////////////////////////////
lpdi->CreateDevice(GUID_SysMouse, &lpdimouse, NULL);

// set cooperation level
lpdimouse->SetCooperativeLevel(main_window_handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);

// set data format
lpdimouse->SetDataFormat(&c_dfDIMouse);

// acquire the mouse
lpdimouse->Acquire();

/////////////////////////////////////////////////////////////////

// set the global mouse position
mouse_x = screen_height/2;
mouse_y = screen_height/2;

// load the master bitmap in with all the graphics
Load_Bitmap_File(&bitmap8bit, "PAINT.BMP");
Set_Palette(bitmap8bit.palette);

// make sure all the surfaces are clean before starting
DDraw_Fill_Surface(lpddsback, 0);
DDraw_Fill_Surface(lpddsprimary, 0);

// create the pointer bob
Create_BOB(&pointer,mouse_x,mouse_y,32,34,1,
           BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME,DDSCAPS_SYSTEMMEMORY);    

// load the image for the pointer in
Load_Frame_BOB(&pointer,&bitmap8bit,0,0,2,BITMAP_EXTRACT_MODE_CELL);  

// create the button bob
Create_BOB(&buttons,0,0,32,34,8,
           BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,DDSCAPS_SYSTEMMEMORY);    

// load buttons in, two banks of 4, all the off's, then all the on's
for (index=0; index<8; index++)
     Load_Frame_BOB(&buttons,&bitmap8bit,index, index%4,index/4,BITMAP_EXTRACT_MODE_CELL);  

// create the bitmap to hold the control panel
Create_Bitmap(&cpanel,500,0,104,424);
Load_Image_Bitmap(&cpanel, &bitmap8bit,150,0,BITMAP_EXTRACT_MODE_ABS);

// create the drawing canvas bitmap
Create_Bitmap(&canvas,0,0,500,SCREEN_HEIGHT);
memset(canvas.buffer,0,canvas.width*canvas.height);
canvas.attr = BITMAP_ATTR_LOADED;

// clear out the canvas
// memset(canvas.buffer,0,canvas.width*canvas.height);

// set clipping rectangle to screen extents so mouse cursor
// doens't mess up at edges
RECT screen_rect = {0,0,screen_width,screen_height};
lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);

// hide the mouse
ShowCursor(FALSE);

// return success
return(1);

} // end Game_Init
Example #2
0
    HRESULT InitForceFeedback()
    {

        HRESULT hr;
        DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };
        LONG rglDirection[2] = { 0, 0 };

        if (FAILED(hr = g_pJoystick->SetCooperativeLevel(GetActiveWindow(), DISCL_EXCLUSIVE | DISCL_BACKGROUND)))
            return hr;

        if (FAILED(hr = g_pJoystick->Acquire()))
            return hr;

        // Autocenter
        ZeroMemory(&g_sAutoCenterConfig, sizeof(g_sAutoCenterConfig));

        g_sAutoCenterConfig.dwStartDelay = 0;

        g_sAutoCenterConfig.dwSize = sizeof(DIEFFECT);
        g_sAutoCenterConfig.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
        g_sAutoCenterConfig.dwDuration = INFINITE;
        g_sAutoCenterConfig.dwSamplePeriod = 0;
        g_sAutoCenterConfig.dwGain = DI_FFNOMINALMAX;
        g_sAutoCenterConfig.dwTriggerButton = DIEB_NOTRIGGER;
        g_sAutoCenterConfig.dwTriggerRepeatInterval = 0;
        g_sAutoCenterConfig.cAxes = 1;
        g_sAutoCenterConfig.rgdwAxes = rgdwAxes;
        g_sAutoCenterConfig.rglDirection = rglDirection;

        g_sAutoCenterConfig.lpEnvelope = 0;
        g_sAutoCenterConfig.dwStartDelay = 0;

        DICONSTANTFORCE cf = { 0 };

        g_sAutoCenterConfig.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
        g_sAutoCenterConfig.lpvTypeSpecificParams = &cf;

        if (FAILED(hr = g_pJoystick->CreateEffect(GUID_ConstantForce, &g_sAutoCenterConfig, &g_pAutoCenterHandle, nullptr)))
            return hr;

        if (FAILED(hr = g_pAutoCenterHandle->Start(INFINITE, 0)))
            return hr;

        // Rumble
        ZeroMemory(&g_sWheelRumbleConfig, sizeof(g_sWheelRumbleConfig));

        g_sWheelRumbleConfig.dwStartDelay = 0;

        g_sWheelRumbleConfig.dwSize = sizeof(DIEFFECT);
        g_sWheelRumbleConfig.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
        g_sWheelRumbleConfig.dwDuration = INFINITE;
        g_sWheelRumbleConfig.dwSamplePeriod = 0;
        g_sWheelRumbleConfig.dwGain = DI_FFNOMINALMAX;
        g_sWheelRumbleConfig.dwTriggerButton = DIEB_NOTRIGGER;
        g_sWheelRumbleConfig.dwTriggerRepeatInterval = 0;
        g_sWheelRumbleConfig.cAxes = 1;
        g_sWheelRumbleConfig.rgdwAxes = rgdwAxes;
        g_sWheelRumbleConfig.rglDirection = rglDirection;

        g_sWheelRumbleConfig.lpEnvelope = 0;
        g_sWheelRumbleConfig.dwStartDelay = 0;

        DIPERIODIC pf = { 0,0,0,0.08 };

        g_sWheelRumbleConfig.cbTypeSpecificParams = sizeof(DIPERIODIC);
        g_sWheelRumbleConfig.lpvTypeSpecificParams = &pf;

        if (FAILED(hr = g_pJoystick->CreateEffect(GUID_Sine, &g_sWheelRumbleConfig, &g_pWheelRumbleHandle, nullptr)))
            return hr;

        if (FAILED(hr = g_pWheelRumbleHandle->Start(INFINITE, 0)))
            return hr;

        return S_OK;
    }
Example #3
0
int DInput_Init_Joystick(int min_x, int max_x, int min_y, int max_y, int dead_zone)
{
// this function initializes the joystick, it allows you to set
// the minimum and maximum x-y ranges 

// first find the f*****g GUID of your particular joystick
lpdi->EnumDevices(DI8DEVCLASS_GAMECTRL, 
                  DInput_Enum_Joysticks, 
                  &joystickGUID, 
                  DIEDFL_ATTACHEDONLY); 

// create a temporary IDIRECTINPUTDEVICE (1.0) interface, so we query for 2
LPDIRECTINPUTDEVICE lpdijoy_temp = NULL;

if (lpdi->CreateDevice(joystickGUID, &lpdijoy, NULL)!=DI_OK)
   return(0);

// set cooperation level
if (lpdijoy->SetCooperativeLevel(main_window_handle, 
	                 DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK)
   return(0);

// set data format
if (lpdijoy->SetDataFormat(&c_dfDIJoystick)!=DI_OK)
   return(0);

// set the range of the joystick
DIPROPRANGE joy_axis_range;

// first x axis
joy_axis_range.lMin = min_x;
joy_axis_range.lMax = max_x;

joy_axis_range.diph.dwSize       = sizeof(DIPROPRANGE); 
joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
joy_axis_range.diph.dwObj        = DIJOFS_X;
joy_axis_range.diph.dwHow        = DIPH_BYOFFSET;

lpdijoy->SetProperty(DIPROP_RANGE,&joy_axis_range.diph);

// now y-axis
joy_axis_range.lMin = min_y;
joy_axis_range.lMax = max_y;

joy_axis_range.diph.dwSize       = sizeof(DIPROPRANGE); 
joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
joy_axis_range.diph.dwObj        = DIJOFS_Y;
joy_axis_range.diph.dwHow        = DIPH_BYOFFSET;

lpdijoy->SetProperty(DIPROP_RANGE,&joy_axis_range.diph);


// and now the dead band
DIPROPDWORD dead_band; // here's our property word

// scale dead zone by 100
dead_zone*=100;

dead_band.diph.dwSize       = sizeof(dead_band);
dead_band.diph.dwHeaderSize = sizeof(dead_band.diph);
dead_band.diph.dwObj        = DIJOFS_X;
dead_band.diph.dwHow        = DIPH_BYOFFSET;

// deadband will be used on both sides of the range +/-
dead_band.dwData            = dead_zone;

// finally set the property
lpdijoy->SetProperty(DIPROP_DEADZONE,&dead_band.diph);

dead_band.diph.dwSize       = sizeof(dead_band);
dead_band.diph.dwHeaderSize = sizeof(dead_band.diph);
dead_band.diph.dwObj        = DIJOFS_Y;
dead_band.diph.dwHow        = DIPH_BYOFFSET;

// deadband will be used on both sides of the range +/-
dead_band.dwData            = dead_zone;


// finally set the property
lpdijoy->SetProperty(DIPROP_DEADZONE,&dead_band.diph);

// acquire the joystick
if (lpdijoy->Acquire()!=DI_OK)
   return(0);

// set found flag
joystick_found = 1;

// return success
return(1);

} // end DInput_Init_Joystick
PsychError PsychHIDOSKbCheck(int deviceIndex, double* scanList)
{
    psych_uint8 keys[1024];
    LPDIRECTINPUTDEVICE8 kb;
    unsigned int i, j;
    double* buttonStates;
    int keysdown;
    double timestamp;
    DWORD cbSize;

    if (deviceIndex == INT_MAX) {
        deviceIndex = PsychHIDGetDefaultKbQueueDevice();
        // Ok, deviceIndex now contains our default keyboard to use - The first suitable keyboard.
    }

    if ((deviceIndex < 0) || (deviceIndex >= ndevices)) {
        // Out of range index:
        PsychErrorExitMsg(PsychError_user, "Invalid 'deviceIndex' specified. No such device!");
    }

    // Get DirectInput keyboard device:
    kb = GetXDevice(deviceIndex);

    // Keyboard queue for this deviceIndex already exists?
    if (NULL == psychHIDKbQueueFirstPress[deviceIndex]) {
        // No. Create one which accepts all keys:
        PsychHIDOSKbQueueCreate(deviceIndex, 0, NULL);
    }

    // Keyboard queue for this device active? If not, we need
    // to start it:
    if (!psychHIDKbQueueActive[deviceIndex]) {
        // Keyboard idle: Need to start it:
        PsychHIDOSKbQueueStart(deviceIndex);

        // Startup to first key delivery takes time. Wait for
        // 50 msecs to be on the safe side:
        PsychYieldIntervalSeconds(0.050);
    }

    // Size of state structure is device dependent:
    switch (info[deviceIndex].dwDevType & 0xff) {
    case DI8DEVTYPE_KEYBOARD:
        cbSize = 256;
        break;

    case DI8DEVTYPE_MOUSE:
    case DI8DEVTYPE_SCREENPOINTER:
        cbSize = sizeof(DIMOUSESTATE2);
        break;

    case DI8DEVTYPE_JOYSTICK:
        cbSize = sizeof(DIJOYSTATE2);
        break;

    default: // Unkown device. Fail.
        cbSize = 0;
    }


    // Query current state snapshot of keyboard:
    memset(keys, 0, sizeof(keys));
    if (DI_OK != kb->GetDeviceState(cbSize, (LPVOID) &keys[0])) {
        printf("PsychHID-ERROR: KbCheck for deviceIndex %i failed, because query of device failed!\n", deviceIndex);
        PsychErrorExitMsg(PsychError_user, "KbCheck failed!");
    }

    // Request current time of query:
    PsychGetAdjustedPrecisionTimerSeconds(&timestamp);

    // Reset overall key state to "none pressed":
    keysdown = 0;

    // Copy out timestamp:
    PsychCopyOutDoubleArg(2, kPsychArgOptional, timestamp);

    // Copy keyboard state:
    PsychAllocOutDoubleMatArg(3, kPsychArgOptional, 1, 256, 1, &buttonStates);
    for (i = 0; i < 256; i++) buttonStates[i] = 0;

    // Keyboard?
    if (cbSize == 256) {
        // Copy button state to output vector, apply scanlist mask, compute
        // resulting overall keysdown state. We ignore keyboard scancode zero and
        // start with 1 instead. We also ignore code 255. These are borderline codes
        // which may do weird things...
        for (i = 1; i < 255; i++) {
            // Compute target key slot for this scancode i:
            j = PsychHIDOSMapKey(i);

            // This key down?
            buttonStates[j] += (keys[i] > 0) ? 1 : 0;
            // Apply scanList mask, if any provided:
            if (scanList && (scanList[j] <= 0)) buttonStates[j] = 0;
            keysdown += (unsigned int) buttonStates[j];
        }
    }

    // Joystick?
    if (cbSize == sizeof(DIJOYSTATE2)) {
        // Copy button state to output vector, apply scanlist mask, compute
        // resulting overall keysdown state. There are 128 buttons at an offset:
        for (i = (8 * sizeof(LONG) + 4 * sizeof(DWORD)); i < (8 * sizeof(LONG) + 4 * sizeof(DWORD)) + 128; i++) {
            // Compute target key slot for this scancode i:
            j = i - (8 * sizeof(LONG) + 4 * sizeof(DWORD));

            // This key down?
            buttonStates[j] += (keys[i] > 0) ? 1 : 0;
            // Apply scanList mask, if any provided:
            if (scanList && (scanList[j] <= 0)) buttonStates[j] = 0;
            keysdown += (unsigned int) buttonStates[j];
        }
    }

    // Mouse?
    if (cbSize == sizeof(DIMOUSESTATE2)) {
        // Copy button state to output vector, apply scanlist mask, compute
        // resulting overall keysdown state. There are 8 buttons at an offset:
        for (i = (3 * sizeof(LONG)); i < (3 * sizeof(LONG)) + 8; i++) {
            // Compute target key slot for this scancode i:
            j = i - (3 * sizeof(LONG));

            // This key down?
            buttonStates[j] += (keys[i] > 0) ? 1 : 0;
            // Apply scanList mask, if any provided:
            if (scanList && (scanList[j] <= 0)) buttonStates[j] = 0;
            keysdown += (unsigned int) buttonStates[j];
        }
    }

    // Copy out overall keystate:
    PsychCopyOutDoubleArg(1, kPsychArgOptional, (keysdown > 0) ? 1 : 0);

    return(PsychError_none);
}
void PsychHIDOSKbQueueStop(int deviceIndex)
{
    LPDIRECTINPUTDEVICE8 kb;
    psych_bool queueActive;
    int i;

    if (deviceIndex < 0) {
        deviceIndex = PsychHIDGetDefaultKbQueueDevice();
        // Ok, deviceIndex now contains our default keyboard to use - The first suitable keyboard.
    }

    if ((deviceIndex < 0) || (deviceIndex >= ndevices)) {
        // Out of range index:
        PsychErrorExitMsg(PsychError_user, "Invalid 'deviceIndex' specified. No such device!");
    }

    // Keyboard queue for this deviceIndex already exists?
    if (NULL == psychHIDKbQueueFirstPress[deviceIndex]) {
        // No. Nothing to do then.
        return;
    }

    // Keyboard queue already stopped?
    if (!psychHIDKbQueueActive[deviceIndex]) return;

    // Get device:
    kb = GetXDevice(deviceIndex);

    // Queue is active. Stop it:
    PsychLockMutex(&KbQueueMutex);

    // Release the device:
    if (DI_OK != kb->Unacquire()) {
        PsychUnlockMutex(&KbQueueMutex);
        printf("PsychHID-ERROR: Tried to stop processing on keyboard queue for deviceIndex %i, but releasing device failed!\n", deviceIndex);
        PsychErrorExitMsg(PsychError_user, "Stopping keyboard queue failed!");
    }

    // Disable state-change event notifications:
    if (DI_OK != kb->SetEventNotification(NULL)) {
        PsychUnlockMutex(&KbQueueMutex);
        printf("PsychHID-ERROR: Tried to stop processing on keyboard queue for deviceIndex %i, but disabling device state notifications failed!\n", deviceIndex);
        PsychErrorExitMsg(PsychError_user, "Stopping keyboard queue failed!");
    }

    // Mark queue logically stopped:
    psychHIDKbQueueActive[deviceIndex] = FALSE;

    PsychUnlockMutex(&KbQueueMutex);

    // Was this the last active queue?
    queueActive = FALSE;
    for (i = 0; i < PSYCH_HID_MAX_DEVICES; i++) {
        queueActive |= psychHIDKbQueueActive[i];
    }

    // If more queues are active then we're done:
    if (queueActive) return;

    // No more active queues. Shutdown the common processing thread:
    PsychLockMutex(&KbQueueMutex);

    KbQueueThreadTerminate = TRUE;

    // Done.
    PsychUnlockMutex(&KbQueueMutex);

    // Shutdown the thread, wait for its termination:
    PsychDeleteThread(&KbQueueThread);
    KbQueueThreadTerminate = FALSE;

    // printf("DEBUG: THREAD JOINED.\n"); fflush(NULL);

    return;
}
int Game_Init(void *parms,  int num_parms)
{
// this function is where you do all the initialization 
// for your game

int index;         // looping var
char filename[80]; // used to build up files names

// initialize directdraw
DDraw_Init(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP);


#if 0 // directinput7 method

// first create the direct input object
if (DirectInputCreateEx(main_instance,DIRECTINPUT_VERSION,IID_IDirectInput7, (void **)&lpdi,NULL)!=DI_OK)
   return(0);

// create a keyboard device  //////////////////////////////////
if (lpdi->CreateDeviceEx(GUID_SysKeyboard, IID_IDirectInputDevice7, (void **)&lpdikey, NULL)!=DI_OK)
   return(0);

#endif


// first create the direct input object
if (DirectInput8Create(main_instance,DIRECTINPUT_VERSION,IID_IDirectInput8, (void **)&lpdi,NULL)!=DI_OK)
   return(0);

// create a keyboard device  //////////////////////////////////
if (lpdi->CreateDevice(GUID_SysKeyboard, &lpdikey, NULL)!=DI_OK)
   return(0);


// set cooperation level
if (lpdikey->SetCooperativeLevel(main_window_handle, 
                 DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK)
    return(0);

// set data format
if (lpdikey->SetDataFormat(&c_dfDIKeyboard)!=DI_OK)
   return(0);

// acquire the keyboard
if (lpdikey->Acquire()!=DI_OK)
   return(0);

///////////////////////////////////////////////////////////

// load the background
Load_Bitmap_File(&bitmap8bit, "REACTOR.BMP");

// set the palette to background image palette
Set_Palette(bitmap8bit.palette);

// create and load the reactor bitmap image
Create_Bitmap(&reactor, 0,0, 640, 480);
Load_Image_Bitmap(&reactor,&bitmap8bit,0,0,BITMAP_EXTRACT_MODE_ABS);
Unload_Bitmap_File(&bitmap8bit);

// now let's load in all the frames for the skelaton!!!

// create skelaton bob
if (!Create_BOB(&skelaton,0,0,56,72,32,
           BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM,DDSCAPS_SYSTEMMEMORY))
   return(0);

// load the frames in 8 directions, 4 frames each
// each set of frames has a walk and a fire, frame sets
// are loaded in counter clockwise order looking down
// from a birds eys view or the x-z plane
for (int direction = 0; direction < 8; direction++)
    { 
    // build up file name
    sprintf(filename,"SKELSP%d.BMP",direction);

    // load in new bitmap file
    Load_Bitmap_File(&bitmap8bit,filename);
 
    Load_Frame_BOB(&skelaton,&bitmap8bit,0+direction*4,0,0,BITMAP_EXTRACT_MODE_CELL);  
    Load_Frame_BOB(&skelaton,&bitmap8bit,1+direction*4,1,0,BITMAP_EXTRACT_MODE_CELL);  
    Load_Frame_BOB(&skelaton,&bitmap8bit,2+direction*4,2,0,BITMAP_EXTRACT_MODE_CELL);  
    Load_Frame_BOB(&skelaton,&bitmap8bit,3+direction*4,0,1,BITMAP_EXTRACT_MODE_CELL);  

    // unload the bitmap file
    Unload_Bitmap_File(&bitmap8bit);

    // set the animation sequences for skelaton
    Load_Animation_BOB(&skelaton,direction,4,skelaton_anims[direction]);

    } // end for direction

// set up stating state of skelaton
Set_Animation_BOB(&skelaton, 0);
Set_Anim_Speed_BOB(&skelaton, 4);
Set_Vel_BOB(&skelaton, 0,0);
Set_Pos_BOB(&skelaton, 0, 128);

// set clipping rectangle to screen extents so mouse cursor
// doens't mess up at edges
RECT screen_rect = {0,0,screen_width,screen_height};
lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);

// hide the mouse
ShowCursor(FALSE);

// return success
return(1);

} // end Game_Init
Example #7
0
void CJoystick::Update()
{
  if (!IsEnabled())
    return;

  int buttonId    = -1;
  int axisId      = -1;
  int hatId       = -1;
  int numhat      = -1;
  int numj        = m_pJoysticks.size();
  if (numj <= 0)
    return;

  // go through all joysticks
  for (int j = 0; j<numj; j++)
  {
    LPDIRECTINPUTDEVICE8 pjoy = m_pJoysticks[j];
    HRESULT hr;
    DIJOYSTATE2 js;           // DInput joystick state

    m_NumAxes = (m_devCaps[j].dwAxes > MAX_AXES) ? MAX_AXES : m_devCaps[j].dwAxes;
    numhat    = (m_devCaps[j].dwPOVs > 4) ? 4 : m_devCaps[j].dwPOVs;

    hr = pjoy->Poll();
    if( FAILED( hr ) )
    {
      int i=0;
      // DInput is telling us that the input stream has been
      // interrupted. We aren't tracking any state between polls, so
      // we don't have any special reset that needs to be done. We
      // just re-acquire and try again.
      hr = pjoy->Acquire();
      while( (hr == DIERR_INPUTLOST) && (i++ < 10)  )
          hr = pjoy->Acquire();

      // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
      // may occur when the app is minimized or in the process of
      // switching, so just try again later
      return;
    }

    // Get the input's device state
    if( FAILED( hr = pjoy->GetDeviceState( sizeof( DIJOYSTATE2 ), &js ) ) )
      return; // The device should have been acquired during the Poll()

    // get button states first, they take priority over axis
    for( int b = 0; b < 128; b++ )
    {
      if( js.rgbButtons[b] & 0x80 )
      {
        m_JoyId = j;
        buttonId = b+1;
        j = numj-1;
        break;
      }
    }

    // get hat position
    m_HatState = SDL_HAT_CENTERED;
    for (int h = 0; h < numhat; h++)
    {
      if((LOWORD(js.rgdwPOV[h]) == 0xFFFF) != true)
      {
        m_JoyId = j;
        hatId = h + 1;
        j = numj-1;
        if ( (js.rgdwPOV[0] > JOY_POVLEFT) || (js.rgdwPOV[0] < JOY_POVRIGHT) )
          m_HatState |= SDL_HAT_UP;

        if ( (js.rgdwPOV[0] > JOY_POVFORWARD) && (js.rgdwPOV[0] < JOY_POVBACKWARD) )
          m_HatState |= SDL_HAT_RIGHT;

        if ( (js.rgdwPOV[0] > JOY_POVRIGHT) && (js.rgdwPOV[0] < JOY_POVLEFT) )
          m_HatState |= SDL_HAT_DOWN;

        if ( js.rgdwPOV[0] > JOY_POVBACKWARD )
          m_HatState |= SDL_HAT_LEFT;
        break;
      }
    }

    // get axis states
    m_Amount[0] = 0;
    m_Amount[1] = js.lX;
    m_Amount[2] = js.lY;
    m_Amount[3] = js.lZ;
    m_Amount[4] = js.lRx;
    m_Amount[5] = js.lRy;
    m_Amount[6] = js.lRz;

    m_AxisId = GetAxisWithMaxAmount();
    if (m_AxisId)
    {
      m_JoyId = j;
      j = numj-1;
      break;
    }
  }

  if(hatId==-1)
  {
    if(m_HatId!=0)
      CLog::Log(LOGDEBUG, "Joystick %d hat %d Centered", m_JoyId, abs(hatId));
    m_pressTicksHat = 0;
    SetHatActive(false);
    m_HatId = 0;
  }
  else
  {
    if(hatId!=m_HatId)
    {
      CLog::Log(LOGDEBUG, "Joystick %d hat %u Down", m_JoyId, hatId);
      m_HatId = hatId;
      m_pressTicksHat = XbmcThreads::SystemClockMillis();
    }
    SetHatActive();
  }

  if (buttonId==-1)
  {
    if (m_ButtonId!=0)
    {
      CLog::Log(LOGDEBUG, "Joystick %d button %d Up", m_JoyId, m_ButtonId);
    }
    m_pressTicksButton = 0;
    SetButtonActive(false);
    m_ButtonId = 0;
  }
  else
  {
    if (buttonId!=m_ButtonId)
    {
      CLog::Log(LOGDEBUG, "Joystick %d button %d Down", m_JoyId, buttonId);
      m_ButtonId = buttonId;
      m_pressTicksButton = XbmcThreads::SystemClockMillis();
    }
    SetButtonActive();
  }

}
Example #8
0
//	this will catch all input keyboard and mouse
//	i may try to make a thread which continuously catches input
void TSRInputSubSystem::CatchAll()
{
#if defined( PLATFORM_MACOSX ) || defined( WIN32 )|| defined( WIN64 )
#if defined( WIN32 )|| defined( WIN64 ) 

	//	this will hold mouse state and position, global for external use
	DIMOUSESTATE		dInputMouseState;

	if ( FAILED( m_lpdimouse->GetDeviceState( sizeof( DIMOUSESTATE ), ( LPVOID ) &dInputMouseState ) ) )
	{
        TSRFatalError( "Error reading mouse" );
    }

	Mouse()->m_DeltaZ = dInputMouseState.lZ;

#endif
    
	int iMouseX = 0;
	int iMouseY = 0;
	bool bLButtonPrevious = Mouse()->m_bLButtonDown;

#ifdef TSR_SDL_ENABLED

	uint8 sdlMouseButtons = SDL_GetMouseState( &iMouseX, &iMouseY ); 
	iMouseY = TSRSystem()->m_DisplayMode.m_uiHeight - iMouseY;

	//	update mouse buttons states
	Mouse()->m_bLButtonDown = ( sdlMouseButtons & SDL_BUTTON( 1 ) ) != 0;
	Mouse()->m_bRButtonDown = ( sdlMouseButtons & SDL_BUTTON( 3 ) ) != 0;
	Mouse()->m_bMButtonDown = ( sdlMouseButtons & SDL_BUTTON( 2 ) ) != 0;

	SDL_GetRelativeMouseState( &Mouse()->m_DeltaX, &Mouse()->m_DeltaY );

#endif

#if defined( WIN32 )|| defined( WIN64 )

	//Mouse()->UpdateLocation( iMouseX, iMouseY );

	Mouse()->m_bLButtonDown = dInputMouseState.rgbButtons[ 0 ] != 0;
	Mouse()->m_bRButtonDown = dInputMouseState.rgbButtons[ 1 ] != 0;
	Mouse()->m_bMButtonDown = dInputMouseState.rgbButtons[ 2 ] != 0;

	Mouse()->m_DeltaX = dInputMouseState.lX;
	Mouse()->m_DeltaY = dInputMouseState.lY;

#endif

	if ( Mouse()->m_bLButtonDown && ( Mouse()->m_DeltaX || Mouse()->m_DeltaY ) )
	{
		TSRSystem()->GetCallBacks()->OnTouchDelta( ( float ) Mouse()->m_DeltaX, ( float ) Mouse()->m_DeltaY, 3 );
	}
	
	if ( Mouse()->m_bLButtonDown && !bLButtonPrevious )
	{
		TSRSystem()->GetCallBacks()->OnTouchEvent( iMouseX, iMouseY, 0 );
	}

	if ( !Mouse()->m_bLButtonDown && bLButtonPrevious )
	{
		TSRSystem()->GetCallBacks()->OnTouchEvent( iMouseX, iMouseY, 1 );
	}

#endif 
}
Example #9
0
/////////////////////////////////////
// Name:	INPMouseUpdate
// Purpose:	update mouse device, we
//			require hMain to get the
//			actual location of the mouse
//			(this is not used in
//			 exclusive mode)
// Output:	mouse updated
// Return:	
/////////////////////////////////////
s32 F_API INPMouseUpdate(void *hMain)
{
	if(!g_pDMouse)
		return RETCODE_SUCCESS;

	u8 i;
	DIMOUSESTATE2 mouseDat={0};

	//update released buttons
	for(i = 0; i < MAXMOUSEBTN; i++)
	{
		if(g_mouseBtn[i] == INPUT_RELEASED)
			g_mouseBtn[i] = INPUT_UP;
	}

	HRESULT hr;

	hr = g_pDMouse->Poll();

	if(FAILED(hr))
	{
		// DInput is telling us that the input stream has been
        // interrupted. We aren't tracking any state between polls, so
        // we don't have any special reset that needs to be done. We
        // just re-acquire and try again.
        hr = g_pDMouse->Acquire();
        while( hr == DIERR_INPUTLOST ) 
            hr = g_pDMouse->Acquire();

        // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
        // may occur when the app is minimized or in the process of 
        // switching, so just try again later 
        return RETCODE_SUCCESS; 
	}

	// Get the input's device state
    if(FAILED(hr = g_pDMouse->GetDeviceState(sizeof(DIMOUSESTATE2), &mouseDat)))
	{ DInputError(hr, L"INPMouseUpdate"); return RETCODE_FAILURE; }

	//check the buttons
	for(i = 0; i < MAXMOUSEBTN; i++)
    {
		if(mouseDat.rgbButtons[i] & INPUT_DOWN)
			g_mouseBtn[i] = INPUT_DOWN;
		else if(g_mouseBtn[i] == INPUT_DOWN)
			g_mouseBtn[i] = INPUT_RELEASED;
	}

	//check location
	if(!g_bExclusive)
	{
		GetCursorPos((LPPOINT)&g_mouseLoc);
		ScreenToClient((HWND)hMain, (LPPOINT)&g_mouseLoc);
	}
	else
	{
		g_mouseLoc.x += mouseDat.lX;

		if(g_mouseLoc.x < 0) g_mouseLoc.x = 0;
		else if(g_mouseLoc.x > g_bound.x) g_mouseLoc.x = g_bound.x;

		g_mouseLoc.y += mouseDat.lY;

		if(g_mouseLoc.y < 0) g_mouseLoc.y = 0;
		else if(g_mouseLoc.y > g_bound.y) g_mouseLoc.y = g_bound.y;
	}

	g_mouseRelX = mouseDat.lX;
	g_mouseRelY = mouseDat.lY;
	g_mouseRelZ = mouseDat.lZ;

	return RETCODE_SUCCESS;
}
Example #10
0
//=============================================================================
// マウスの初期化
//=============================================================================
HRESULT InitMouse(HINSTANCE hInstance, HWND hWnd)
{
	HRESULT hr;

	// 入力処理の初期化
	hr = InitInput(hInstance, hWnd);
	if(FAILED(hr))
	{
		MessageBox(hWnd, "DirectInputオブジェクトが作れねぇ!", "警告!", MB_ICONWARNING);
		return hr;
	}

	// デバイスオブジェクトを作成
	hr = g_pInput->CreateDevice(GUID_SysMouse, &g_pDevMouse, NULL);
	if(FAILED(hr))
	{
		MessageBox(hWnd, "マウスがねぇ!", "警告!", MB_ICONWARNING);
		return hr;
	}

	// データフォーマットを設定
	hr = g_pDevMouse->SetDataFormat(&c_dfDIMouse2);
	if(FAILED(hr))
	{
		MessageBox(hWnd, "マウスのデータフォーマットを設定できませんでした。", "警告!", MB_ICONWARNING);
		return hr;
	}

	// 協調モードを設定(フォアグラウンド&非排他モード)
	hr = g_pDevMouse->SetCooperativeLevel(hWnd, (DISCL_FOREGROUND | DISCL_NONEXCLUSIVE));
	if(FAILED(hr))
	{
		MessageBox(hWnd, "マウスの協調モードを設定できませんでした。", "警告!", MB_ICONWARNING);
		return hr;
	}

	// デバイスのプロパティを設定
	{
		DIPROPDWORD dipdw;

		dipdw.diph.dwSize = sizeof(dipdw);
		dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
		dipdw.diph.dwObj = 0;
		dipdw.diph.dwHow = DIPH_DEVICE;
		dipdw.dwData = DIPROPAXISMODE_REL;

		hr = g_pDevMouse->SetProperty(DIPROP_AXISMODE, &dipdw.diph);
		if(FAILED(hr))
		{
			MessageBox(hWnd, "マウスのデバイスのプロパティを設定できませんでした。", "警告!", MB_ICONWARNING);
			return hr;
		}
	}

	// マウスへのアクセス権を獲得(入力制御開始)
	g_pDevMouse->Acquire();

	//初期化
	ZeroMemory(&g_mouseState, sizeof DIMOUSESTATE2);
	ZeroMemory(&g_mouseStateTrigger, sizeof DIMOUSESTATE2);

	return S_OK;
}
bool DIDevice::Open()
{
	m_sName = ConvertACPToUTF8( JoystickInst.tszProductName );

	LOG->Trace( "Opening device '%s'", m_sName.c_str() );
	buffered = true;

	LPDIRECTINPUTDEVICE8 tmpdevice;

	// load joystick
	HRESULT hr = g_dinput->CreateDevice( JoystickInst.guidInstance, &tmpdevice, NULL );
	if ( hr != DI_OK )
	{
		LOG->Info( hr_ssprintf(hr, "OpenDevice: IDirectInput_CreateDevice") );
		return false;
	}
	hr = tmpdevice->QueryInterface( IID_IDirectInputDevice8, (LPVOID *) &Device );
	tmpdevice->Release();
	if ( hr != DI_OK )
	{
		LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice::QueryInterface", m_sName.c_str()) );
		return false;
	}

	int coop = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;
	if( type == KEYBOARD )
		coop = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND;

	hr = Device->SetCooperativeLevel( GraphicsWindow::GetHwnd(), coop );
	if ( hr != DI_OK )
	{
		LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice2::SetCooperativeLevel", m_sName.c_str()) );
		return false;
	}

	switch(type)
	{
		case KEYBOARD:
			hr = Device->SetDataFormat( &c_dfDIKeyboard );
			break;
		case JOYSTICK:
			hr = Device->SetDataFormat( &c_dfDIJoystick );
			break;
		case MOUSE:
			hr = Device->SetDataFormat( &c_dfDIMouse );
			break;
	}
	if ( hr != DI_OK )
	{
		LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice2::SetDataFormat", m_sName.c_str()) );
		return false;
	}

	switch( type )
	{
		case JOYSTICK:
			Device->EnumObjects( DIJoystick_EnumDevObjectsProc, this, DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
			break;
		case KEYBOARD:
			// Always 256-button.
			for( int b = 0; b < 256; ++b )
			{
				input_t in;
				in.type = in.KEY;

				in.num = ConvertScancodeToKey(b);
				in.ofs = b;
				buttons++;
				Inputs.push_back(in);
			}
			break;
		case MOUSE:
			Device->EnumObjects( DIMouse_EnumDevObjectsProc, this, DIDFT_BUTTON | DIDFT_AXIS | DIDFT_ANYINSTANCE );
			break;
	}

	{
		DIPROPDWORD dipdw;
		memset(&dipdw, 0, sizeof(dipdw));
		dipdw.diph.dwSize = sizeof(dipdw);
		dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
		dipdw.diph.dwObj = 0;
		dipdw.diph.dwHow = DIPH_DEVICE;
		dipdw.dwData = INPUT_QSIZE;
		hr = Device->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
		if ( hr == DI_POLLEDDEVICE )
		{
			/* This device doesn't support buffering, so we're forced
			 * to use less reliable polling. */
			buffered = false;
		}
		else if ( hr != DI_OK )
		{
			LOG->Info( hr_ssprintf(hr, "OpenDevice(%s): IDirectInputDevice2::SetProperty", m_sName.c_str()) );
			return false;
		}
	}

	return true;
}
Example #12
0
//=======================================================================
// get range for an axis
static HRESULT	GetDIAxisRange(LPDIRECTINPUTDEVICE8 device, uint offset, DWORD type, sint &min, sint &max)
{
	DIPROPRANGE diprg;
    diprg.diph.dwSize       = sizeof(DIPROPRANGE);
    diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    diprg.diph.dwHow        = DIPH_BYOFFSET;
    diprg.diph.dwObj        = offset;

	// Set the range for the axis
	HRESULT r = device->GetProperty(DIPROP_RANGE, &diprg.diph);

	if (r == DIERR_OBJECTNOTFOUND)
	{
		// try from its ID
		diprg.diph.dwHow        = DIPH_BYID;
		diprg.diph.dwObj        = type;

		// Set the range for the axis
		HRESULT r = device->GetProperty(DIPROP_RANGE, &diprg.diph);
		if (r !=  DI_OK)
		{
			// setup default values ...
			min = 0;
			max = 65535;
			return r;
		}
	}
	else if (r != DI_OK)
	{
		min = 0;
		max = 65535;
		return r;
	}


/*	switch (r)
	{
		default:
			nlinfo("ok");
		break;
		case DIERR_INVALIDPARAM:
			nlinfo("invalid param");
		break;
		case DIERR_NOTEXCLUSIVEACQUIRED:
			nlinfo("DIERR_NOTEXCLUSIVEACQUIRED");
		break;
		case DIERR_NOTINITIALIZED:
			nlinfo("DIERR_NOTINITIALIZED");
		break;
		case DIERR_OBJECTNOTFOUND:
			nlinfo("DIERR_OBJECTNOTFOUND");
		break;
		case DIERR_UNSUPPORTED:
			nlinfo("DIERR_UNSUPPORTED");
		break;
	}*/


	min = (sint) diprg.lMin;
	max = (sint) diprg.lMax;

	return r;
}
bool ReadJoystick(F32 axes[MaxJoystickAxes], U32 &buttonMask, U32 &hatMask)
{
    // mark: it's ok
    // mark: it's called "winJoystick"
    // mark: it's supposed to be gross.

    DIJOYSTATE2 js;       // DInput joystick state

    if(!gJoystick)
        return false;

    if(FAILED(gJoystick->Poll() ) )
    {
        HRESULT hr;
        hr = gJoystick->Acquire();

        while( hr == DIERR_INPUTLOST )
            hr = gJoystick->Acquire();
        return false;
    }

    // Get the input's device state
    if(FAILED(gJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &js ) ) )
        return false; // The device should have been acquired during the Poll()

    F32 scale = 1 / 32768.0f;
    axes[0] = (F32(js.lX) - 32768.0f) * scale;
    axes[1] = (F32(js.lY) - 32768.0f) * scale;
    axes[2] = (F32(js.lZ) - 32768.0f) * scale;
    axes[3] = (F32(js.lRx) - 32768.0f) * scale;
    axes[4] = (F32(js.lRy) - 32768.0f) * scale;
    axes[5] = (F32(js.lRz) - 32768.0f) * scale;
    axes[6] = (F32(js.rglSlider[0]) - 32768.0f) * scale;
    axes[7] = (F32(js.rglSlider[1]) - 32768.0f) * scale;
    axes[8] = 0;
    axes[9] = 0;
    axes[10] = 0;
    axes[11] = 0;

    // check the state of the buttons:
    buttonMask = 0;
    U32 pov = js.rgdwPOV[0];

    for( U32 i = 0; i < 12; i++ )
        if((js.rgbButtons[i] & 0x80) != 0)
            buttonMask |= BIT(i);

    switch(pov)
    {
    case 0:
        hatMask |= ControllerButtonDPadUp;
        break;
    case 4500:
        hatMask |= ControllerButtonDPadUp | ControllerButtonDPadRight;
        break;
    case 9000:
        hatMask |= ControllerButtonDPadRight;
        break;
    case 13500:
        hatMask |= ControllerButtonDPadRight | ControllerButtonDPadDown;
        break;
    case 18000:
        hatMask |= ControllerButtonDPadDown;
        break;
    case 22500:
        hatMask |= ControllerButtonDPadDown | ControllerButtonDPadLeft;
        break;
    case 27000:
        hatMask |= ControllerButtonDPadLeft;
        break;
    case 31500:
        hatMask |= ControllerButtonDPadLeft | ControllerButtonDPadUp;
        break;
    }
    return true;
}
int Game_Main(void *parms, int num_parms)
{
// this is the workhorse of your game it will be called
// continuously in real-time this is like main() in C
// all the calls for you game go here!

int index; // looping var


// check of user is trying to exit
if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
    PostMessage(main_window_handle, WM_DESTROY,0,0);

// start the timing clock
Start_Clock();

// clear the drawing surface
DDraw_Fill_Surface(lpddsback, 0);

// get the input from the mouse
lpdimouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mouse_state);

// move the mouse cursor
mouse_x+=(mouse_state.lX);
mouse_y+=(mouse_state.lY);

// test bounds

// first x boundaries
if (mouse_x >= screen_width)
   mouse_x = screen_width-1;
else
if (mouse_x < 0)
   mouse_x = 0;

// now the y boundaries
if (mouse_y >= screen_height)
   mouse_y= screen_height-1;
else
if (mouse_y < 0)
   mouse_y = 0;

// position the pointer bob to the mouse coords
pointer.x = mouse_x - 16;
pointer.y = mouse_y - 16;

// test what the user is doing with the mouse
if ((mouse_x > 3) && (mouse_x < 500-3) && 
    (mouse_y > 3) && (mouse_y < SCREEN_HEIGHT-3))
   {
   // mouse is within canvas region

   // if left button is down then draw
   if (mouse_state.rgbButtons[0])
      {
      // test drawing mode
      if (buttons_state[BUTTON_PENCIL])
         {
         // draw a pixel 
         Draw_Pixel(mouse_x, mouse_y, mouse_color, canvas.buffer, canvas.width);
         Draw_Pixel(mouse_x+1, mouse_y, mouse_color, canvas.buffer, canvas.width);
         Draw_Pixel(mouse_x, mouse_y+1, mouse_color, canvas.buffer, canvas.width);
         Draw_Pixel(mouse_x+1, mouse_y+1, mouse_color, canvas.buffer, canvas.width);
         }
      else
         {
         // draw spray
         for (index=0; index<10; index++)
             {
             // get next particle
             int sx=mouse_x-8+rand()%16;
             int sy=mouse_y-8+rand()%16;
            
             // make sure particle is in bounds
             if (sx > 0 && sx < 500 && sy > 0 && sy < screen_height)
                Draw_Pixel(sx, sy, mouse_color, canvas.buffer, canvas.width);
             } // end for index

         } // end else

      } // end if left button
    else // right button is eraser
    if (mouse_state.rgbButtons[1])
       {
       // test drawing mode
       if (buttons_state[BUTTON_PENCIL]) 
          {
          // erase a pixel 
          Draw_Pixel(mouse_x, mouse_y, 0, canvas.buffer, canvas.width);
          Draw_Pixel(mouse_x+1, mouse_y, 0, canvas.buffer, canvas.width);
          Draw_Pixel(mouse_x, mouse_y+1, 0, canvas.buffer, canvas.width);
          Draw_Pixel(mouse_x+1, mouse_y+1, 0, canvas.buffer, canvas.width);
          } // end if
       else
          {
          // erase spray
          for (index=0; index<20; index++)
              {
              // get next particle
              int sx=mouse_x-8+rand()%16;
              int sy=mouse_y-8+rand()%16;
            
              // make sure particle is in bounds
              if (sx > 0 && sx < 500 && sy > 0 && sy < screen_height)
                 Draw_Pixel(sx, sy, 0, canvas.buffer, canvas.width);
              } // end for index
          
          } // end else
       
       } // end if left button
  
   } // end if
else
if ( (mouse_x > 500+16) && (mouse_x < 500+16+8*9) &&
     (mouse_y > 8)      && (mouse_y < 8+32*9))
   {
   // within palette

   // test if button left button is down
   if (mouse_state.rgbButtons[0])
      {
      // see what color cell user is pointing to
      int cell_x = (mouse_x - (500+16))/9;
      int cell_y = (mouse_y - (8))/9;

      // change color
      mouse_color = cell_x + cell_y*8;

      } // end if
   } // end if
else
if ((mouse_x > 500) && (mouse_x < (500+100)) &&
    (mouse_y > 344) && (mouse_y < (383+34)) )
   {  
   // within button area
   // test for each button
   for (index=0; index<4; index++)
       {
       if ((mouse_x > buttons_x[index]) && (mouse_x < (buttons_x[index]+32)) &&
           (mouse_y > buttons_y[index]) && (mouse_y < (buttons_y[index]+34)) )
           break;

       } // end for

   // at this point we know where the user is, now determine what he
   // is doing with the buttons
   switch(index)
         {
         case BUTTON_SPRAY:
             {
             // if left button is down simply activate spray mode
             if (mouse_state.rgbButtons[0])
                {
                // depress button
                buttons_state[index] = 1;

               // de-activate pencil mode
                buttons_state[BUTTON_PENCIL] = 0;
                } // end if
             else
                {
                // make sure button is up
                // buttons_state[index] = 0;
                } // end else

             } break;
         
         case BUTTON_PENCIL:
             {
             // if left button is down activate spray mode
             if (mouse_state.rgbButtons[0])
                {
                // depress button
                buttons_state[index] = 1;

                // de-activate spray mode
                buttons_state[BUTTON_SPRAY] = 0;

                } // end if
             else
                {
                // make sure button is up
                // buttons_state[index] = 0;
                } // end else

             } break;

         case BUTTON_ERASE:
             {
             // test if left button is down, if so clear screen
             if (mouse_state.rgbButtons[0])
                {
                // clear memory
                memset(canvas.buffer,0,canvas.width*canvas.height);

                // depress button
                buttons_state[index] = 1;
                } // end if
             else
                {
                // make sure button is up
                buttons_state[index] = 0;
                } // end else
             } break;
         
         case BUTTON_EXIT:
             {
             // test if left button down, if so bail
             if (mouse_state.rgbButtons[0])
                  PostMessage(main_window_handle, WM_DESTROY,0,0);

             } break;

         } // end switch

   } // end if
else
   {
   // no mans land

   } // end else

// lock back buffer
DDraw_Lock_Back_Surface();

// draw the canvas
Draw_Bitmap(&canvas, back_buffer, back_lpitch,0);

// draw control panel
Draw_Bitmap(&cpanel,back_buffer,back_lpitch,0);

// unlock back buffer
DDraw_Unlock_Back_Surface();

// draw the color palette
for (int col=0; col < 256; col++)
    {
    Draw_Rectangle(500+16+(col%8)*9,   8+(col/8)*9,
                   500+16+(col%8)*9+8, 8+(col/8)*9+8,
                   col,lpddsback);
    
    } // end for col

// draw the current color selected
Draw_Rectangle(533,306,533+34,306+34,mouse_color,lpddsback);

// draw the buttons
for (index=0; index<4; index++)
    {
    // set position of button bob
    buttons.x = buttons_x[index];
    buttons.y = buttons_y[index];

    // now select the on/off frame based on if the
    // button is off
    if (buttons_state[index]==0)
        buttons.curr_frame = index;
    else // button is on
        buttons.curr_frame = index+4;

    // draw the button
    Draw_BOB(&buttons, lpddsback);

    } // end for index

static int green = 0;

// display coords
sprintf(buffer,"Pointer (%d,%d)",mouse_x,mouse_y);
Draw_Text_GDI(buffer, 8,screen_height - 16,RGB(0,255,0),lpddsback);
Draw_Text_GDI("T3D Paint Version 2.0 - Press <ESC> to Exit.",0,0,RGB(0,(green & 255),0),lpddsback);

// a little animation
++green;

// draw the cursor last
Draw_BOB(&pointer,lpddsback);

// flip the surfaces
DDraw_Flip();

// sync to 30 fps
Wait_Clock(30);

// return success
return(1);

} // end Game_Main
Example #15
0
//-----------------------------------------------------------------------------
// Name: OnLeftButtonDown()
// Desc: If we are drawing a curve, then read buffered data and draw
//      lines from point to point.  By reading buffered data, we can
//      track the motion of the mouse accurately without coalescing.
//
//      This function illustrates how a non-message-based program can
//      process buffered data directly from a device, processing
//      messages only occasionally (as required by Windows).
//
//      This function also illustrates how an application can piece
//      together buffered data elements based on the sequence number.
//      A single mouse action (e.g., moving diagonally) is reported
//      as a series of events, all with the same sequence number.
//      Zero is never a valid DirectInput sequence number, so it is
//      safe to use it as a sentinel value.
//-----------------------------------------------------------------------------
VOID OnLeftButtonDown( HWND hWnd )
{
    HRESULT             hr;
    LEFTBUTTONINFO      lbInfo;
    BOOL                bDone;
    DIDEVICEOBJECTDATA  od;
    DWORD               dwElements;
    MSG                 msg;

    // For performance, draw directly onto the window's DC instead of
    // invalidating and waiting for the WM_PAINT message.  Of course,
    // we always draw onto our bitmap, too, since that's what really
    // counts.

    // hide cursor and initialize button info with cursor position
    StartPenDraw( hWnd, &lbInfo );
    InvalidateCursorRect( hWnd );
    UpdateWindow( hWnd );

    // Keep reading data elements until we see a "mouse button up" event.
    bDone = FALSE;
    while( !bDone ) 
    {
        dwElements = 1;
        hr = g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), 
                                      &od, &dwElements, 0 );
        if( FAILED(hr) )       
            break;

        // If theres no data available, finish the element 
        // we have been collecting, and then process our message 
        // queue so the system doesn't think the app has hung.
        if( dwElements == 0 ) 
        {
            // if there is a partial motion, flush it out 
            OnLeftButtonDown_FlushMotion( &lbInfo );

            while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) 
            {
                // If it's a quit message, we're outta here 
                if( msg.message == WM_QUIT ) 
                {
                    // Re-post the quit message so the
                    // outer loop will see it and exit.
                    PostQuitMessage( (int)msg.wParam );
                    bDone = TRUE;                    
                    break;
                } 
                else 
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
            }
            continue;
        }

        // If this is the start of a new event, flush out the old one 
        if( od.dwSequence != lbInfo.dwSeqLastSeen ) 
        {
            OnLeftButtonDown_FlushMotion( &lbInfo );
            lbInfo.dwSeqLastSeen = od.dwSequence;
        }

        // Look at the element to see what happened 
        switch( od.dwOfs ) 
        {
            case DIMOFS_X:      // Mouse horizontal motion 
                UpdateCursorPosition( od.dwData, 0 );
                lbInfo.bMoved = TRUE;
                break;

            case DIMOFS_Y:      // Mouse vertical motion 
                UpdateCursorPosition( 0, od.dwData );
                lbInfo.bMoved = TRUE;
                break;

            case DIMOFS_BUTTON0: // Button 0 pressed or released 
            case DIMOFS_BUTTON1: // Button 1 pressed or released 
                if( ( g_bSwapMouseButtons  && DIMOFS_BUTTON1 == od.dwOfs ) ||
                    ( !g_bSwapMouseButtons && DIMOFS_BUTTON0 == od.dwOfs ) )
                {
                    if( !(od.dwData & 0x80) ) 
                    { 
                        // Button released, so flush out dregs 
                        bDone = TRUE;
                        OnLeftButtonDown_FlushMotion( &lbInfo ); 
                    }
                }
                break;
        }
    }

    ReleaseDC( hWnd, lbInfo.hdcWindow );

    // Re-show the cursor now that scrawling is finished 
    FinishPenDraw( hWnd );
    InvalidateCursorRect( hWnd );
}
Example #16
0
void input_Proc(const xhn::vector<input_buffer>& buffer)
{
    if(g_pMouse != NULL)
    {
        DIDEVICEOBJECTDATA didod[DINPUT_BUFFERSIZE]; // Receives buffered data
        DWORD               dwElements;
        HRESULT             hr;

        hr = DIERR_INPUTLOST;

        memset(didod, 0, sizeof(didod));
        dwElements = DINPUT_BUFFERSIZE;
        hr = g_pMouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), didod, &dwElements, 0);
        if (hr != DI_OK)
        {
            hr = g_pMouse->Acquire();
            if(FAILED(hr))
                return;
            hr = g_pMouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), didod, &dwElements, 0);
        }

        if(FAILED(hr))
        {
            if (hr == (HRESULT)DIERR_INPUTLOST)
                printf("DIERR_INPUTLOST\n");
            if (hr == (HRESULT)DIERR_INVALIDPARAM)
                printf("DIERR_INVALIDPARAM\n");
            if (hr == (HRESULT)DIERR_NOTACQUIRED)
                printf("DIERR_NOTACQUIRED\n");
            if (hr == (HRESULT)DIERR_NOTBUFFERED)
                printf("DIERR_NOTBUFFERED\n");
            if (hr == (HRESULT)DIERR_NOTINITIALIZED)
                printf("DIERR_NOTINITIALIZED\n");

            return;
        }
        else
        {
            for(DWORD i=0; i<dwElements; i++)
            {
                input_event event;
                memset(&event, 0, sizeof(event));

                event.time_stamp = didod[i].dwTimeStamp;
                if (didod[i].dwOfs == (DWORD)DIMOFS_X)
                {
                    int disp = didod[i].dwData;
                    event.info.mouse_info.mouse_move_info.x = disp;
                    event.type = MouseMoveEvent;
                }
                else if (didod[i].dwOfs == (DWORD)DIMOFS_Y)
                {
                    int disp = didod[i].dwData;
                    event.info.mouse_info.mouse_move_info.y = disp;
                    event.type = MouseMoveEvent;
                }
                else if (didod[i].dwOfs == (DWORD)DIMOFS_BUTTON0)
                {
                    if (didod[i].dwData & 0x80)
                        event.type = MouseButtonDownEvent;
                    else
                        event.type = MouseButtonUpEvent;
                    event.info.mouse_info.mouse_button_info = LeftButton;
                }
                else if (didod[i].dwOfs == (DWORD)DIMOFS_BUTTON1)
                {
                    if (didod[i].dwData & 0x80)
                        event.type = MouseButtonDownEvent;
                    else
                        event.type = MouseButtonUpEvent;
                    event.info.mouse_info.mouse_button_info = RightButton;
                }
                else if (didod[i].dwOfs == (DWORD)DIMOFS_BUTTON2)
                {
                    if (didod[i].dwData & 0x80)
                        event.type = MouseButtonDownEvent;
                    else
                        event.type = MouseButtonUpEvent;
                    event.info.mouse_info.mouse_button_info = MiddleButton;
                }
                else
                    continue;
				for (euint i = 0; i < buffer.size(); i++) {
					RWBuffer input_buffer = buffer[i].input_buffer;
					InterRWBuffer inter_input_buffer = buffer[i].inter_input_buffer;
					inter_input_buffer.write(input_buffer, (const euint*)&event, sizeof(event));
				}
            }
            POINT curPos;
            GetCursorPos(&curPos);
            ScreenToClient(g_hwnd, &curPos);
            input_event event;
            event.type = MouseAbsolutePositionEvent;
            event.info.mouse_info.mouse_abs_pos.x = curPos.x;
            event.info.mouse_info.mouse_abs_pos.y = curPos.y;
            ///inter_input_buffer.write(input_buffer, (const euint*)&event, sizeof(event));
			for (euint i = 0; i < buffer.size(); i++) {
				RWBuffer input_buffer = buffer[i].input_buffer;
				InterRWBuffer inter_input_buffer = buffer[i].inter_input_buffer;
				inter_input_buffer.write(input_buffer, (const euint*)&event, sizeof(event));
			}
        }

    }
    if(g_pKeyboard != NULL)
    {
        DIDEVICEOBJECTDATA didod[DINPUT_BUFFERSIZE]; // Receives buffered data
        DWORD               dwElements;
        HRESULT             hr;

        hr = DIERR_INPUTLOST;

        memset(didod, 0, sizeof(didod));
        dwElements = DINPUT_BUFFERSIZE;
        hr = g_pKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), didod, &dwElements, 0);
        if (hr != DI_OK)
        {
            hr = g_pKeyboard->Acquire();
            if(FAILED(hr))
                return;
            hr = g_pKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), didod, &dwElements, 0);
        }

        if(FAILED(hr))
        {
            if (hr == (HRESULT)DIERR_INPUTLOST)
                printf("DIERR_INPUTLOST\n");
            if (hr == (HRESULT)DIERR_INVALIDPARAM)
                printf("DIERR_INVALIDPARAM\n");
            if (hr == (HRESULT)DIERR_NOTACQUIRED)
                printf("DIERR_NOTACQUIRED\n");
            if (hr == (HRESULT)DIERR_NOTBUFFERED)
                printf("DIERR_NOTBUFFERED\n");
            if (hr == (HRESULT)DIERR_NOTINITIALIZED)
                printf("DIERR_NOTINITIALIZED\n");

            return;
        }
        else
        {
            for(DWORD i=0; i<dwElements; i++)
            {
                input_event event;
                memset(&event, 0, sizeof(event));

                event.time_stamp = didod[i].dwTimeStamp;
                if (didod[i].dwData & 0x80)
                    event.type = KeyDownEvent;
                else
                    event.type = KeyUpEvent;
                event.info.key_info = didod[i].dwOfs & 0xff;
                ///inter_input_buffer.write(input_buffer, (const euint*)&event, sizeof(event));
				for (euint i = 0; i < buffer.size(); i++) {
					RWBuffer input_buffer = buffer[i].input_buffer;
					InterRWBuffer inter_input_buffer = buffer[i].inter_input_buffer;
					inter_input_buffer.write(input_buffer, (const euint*)&event, sizeof(event));
				}
            }
        }

    }
}
Example #17
0
HRESULT InitD3D(HINSTANCE hInstance)
{
	// 先创建DInput和DSound
	if(FAILED(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&g_pDI, NULL)))
		return E_FAIL;
	if(FAILED(g_pDI->CreateDevice(GUID_SysKeyboard, &g_pDIKey, NULL)))
		return E_FAIL;
	if(FAILED(g_pDI->CreateDevice(GUID_SysMouse, &g_pDIMouse, NULL)))
		return E_FAIL;
		// 设置参数
	if(FAILED(g_pDIKey->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))
		return E_FAIL;
	if(FAILED(g_pDIKey->SetDataFormat(&c_dfDIKeyboard)))
		return E_FAIL;
	if(FAILED(g_pDIMouse->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))
		return E_FAIL;
	if(FAILED(g_pDIMouse->SetDataFormat(&c_dfDIMouse)))
		return E_FAIL;
		
		// 缓冲输入,设置数据格式和属性
	DIPROPDWORD dipdw;
	dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
	dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
	dipdw.diph.dwObj        = 0;
	dipdw.diph.dwHow        = DIPH_DEVICE;
	dipdw.dwData            = SAMPLE_BUFFER_SIZE; // Arbitary buffer size

#ifdef USE_BUFFERED_KEYBOARD_INPUT
	if( FAILED( g_pDIKey->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
		return E_FAIL;
#endif
#ifdef USE_BUFFERED_MOUSE_INPUT
	if( FAILED( g_pDIMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
		return E_FAIL;
#endif

		// 开始
	g_pDIKey->Acquire();
	g_pDIMouse->Acquire();



	// 初始化D3D
	if(NULL==(d3d=Direct3DCreate9(D3D_SDK_VERSION)))
		  return E_FAIL;

	//查询当前显卡模式,Desktop是目前桌面设置,d3ddm总是当前使用全屏模式的设置,即使是窗口模式,颜色数值也总和当前的一样
	if(FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DesktopDisplayMode)))
		  return E_FAIL;
	if(FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
		return E_FAIL;

	//全屏的话默认是32位色
	if(!WindowMode) d3ddm.Format = D3DFMT_X8R8G8B8;

	//查询设备能力,并设置顶点处理器模式
	DWORD UserVertexShaderProcessing;

	d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps);

	if(FAILED(DetectDeviceCaps())) return E_FAIL;

	if(d3dcaps.VertexShaderVersion < D3DVS_VERSION(1, 0))
		UserVertexShaderProcessing=D3DCREATE_HARDWARE_VERTEXPROCESSING;
	else
		UserVertexShaderProcessing=D3DCREATE_SOFTWARE_VERTEXPROCESSING;

//创建D3D设备
	ZeroMemory(&d3dpp,sizeof(d3dpp));

	d3dpp.Windowed = WindowMode;
	d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
	d3dpp.hDeviceWindow = hWnd;
	d3dpp.BackBufferCount = 1;
	d3dpp.BackBufferWidth = d3ddm.Width;
	d3dpp.BackBufferHeight = d3ddm.Height;
	d3dpp.EnableAutoDepthStencil = TRUE;
	
	if(WindowMode)
	{
		d3ddm.Format = DesktopDisplayMode.Format;
		d3dpp.BackBufferWidth = WindowWidth;
		d3dpp.BackBufferHeight = WindowHeight;
	}

	d3dpp.BackBufferFormat = d3ddm.Format;

	if(d3ddm.Format == D3DFMT_X8R8G8B8)
	{
		d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
		TextureFormat = D3DFMT_A8R8G8B8;
	}
	else
	{
		d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
		TextureFormat = D3DFMT_A4R4G4B4;
	}


	// 先强制以硬件顶点方式创建设备(为了不漏掉MX440这种不支持VS但支持T&L的显卡,XIXI)
	UserVertexShaderProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
	HRESULT hr = d3d->CreateDevice( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd, UserVertexShaderProcessing, &d3dpp, &d3ddevice);
	// 这种错误表示顶点处理方式不被硬件支持,强制以软件方式创建设备(为了兼容不支持T&L的DX7显卡,比如某些集成显卡)
	if(hr == D3DERR_INVALIDCALL)
	{
		mymessage("警告:显卡不支持硬件顶点处理,强制以软件方式创建设备,性能会急剧下降!!!");
		UserVertexShaderProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
		hr = d3d->CreateDevice( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd, UserVertexShaderProcessing, &d3dpp, &d3ddevice);
	}
	// 全部失败?有问题吧?
	if(FAILED(hr))
	{
		char szErrorInfo[512] = "";
		sprintf(szErrorInfo, "创建D3D设备失败!请检查系统或硬件设置!比如显卡驱动程序或DirectX是否安装正确!错误号%x", hr);
		mymessage(szErrorInfo);
		return E_FAIL;
	}

	// Shader版本检测
	char pVSVersion[7] = "", pPSVersion[7] = "";
	char pNeedVSVersion[7] = USE_VSVERSION, pNeedPSVersion[7] = USE_PSVERSION;
	char szErrorInfo[100] = "";

#ifdef USE_PIXELSHADER
	// 判断PS版本
	memcpy(pPSVersion, D3DXGetPixelShaderProfile(d3ddevice), 7);
	// 2.x中'b'虽然字母数值大于'a',但它从支持度上来看是小于a的,所以这里强制把它置为小于'a',以便后面比较
	if(pPSVersion[3] == '2' && pPSVersion[5] == 'b')
		pPSVersion[5] = 'a'-1;
	if(pNeedPSVersion[3] == '2' && pNeedPSVersion[5] == 'b')
		pNeedPSVersion[5] = 'a'-1;
	if(pPSVersion[3]<pNeedPSVersion[3] || pPSVersion[3]==pNeedPSVersion[3]&&pPSVersion[5]<pNeedPSVersion[5])
	{
		sprintf(szErrorInfo, "不支持Pixel Shader %c.%c!", pNeedPSVersion[3], pNeedPSVersion[5]);
		mymessage(szErrorInfo);	return E_FAIL;
	}
	
	// 判断PS2.0x的条件是否符合程序的最小需求
	if(!strcmp(USE_PSVERSION, "ps_2_a") || !strcmp(USE_PSVERSION, "ps_2_b") || !strcmp(USE_PSVERSION, "ps_2_x"))
	{
		BOOL bFlowControl = FALSE;
#ifdef PS2x_USE_FLOWCONTROL
		bFlowControl = TRUE;
#endif

		if(!CheckPS2xSupport(PS2x_USE_MAXNUM_TEMP, bFlowControl))
		{
			sprintf(szErrorInfo, "不完整支持Pixel Shader 2.x,无法执行程序!");
			mymessage(szErrorInfo);	return E_FAIL;
		}
	}


#endif USE_PIXELSHADER

#ifdef USE_VERTEXSHADER
	BOOL bSoftwareVertexProcessing = FALSE;
	// 完全不支持的,要跳过版本检测,否则D3DXGetVertexShaderProfile会返回空指针造成非法操作
	if((d3dcaps.VertexShaderVersion&0xffff) == 0) 
	{
		bSoftwareVertexProcessing = TRUE;
	}
	else
	{
		// 判断VS版本
		memcpy(pVSVersion, D3DXGetVertexShaderProfile(d3ddevice), 7);
		if(pVSVersion[3]<pNeedVSVersion[3] || pVSVersion[3]==pNeedVSVersion[3]&&pVSVersion[5]<pNeedVSVersion[5])
		{
			bSoftwareVertexProcessing = TRUE;
		}
		// 判断VS2.0x的条件是否符合程序的最小需求
		if(!strcmp(USE_VSVERSION, "vs_2_a") || !strcmp(USE_VSVERSION, "vs_2_b") || !strcmp(USE_VSVERSION, "vs_2_x"))
		{
#ifdef VS2a_USE_MAXNUM_TEMP
			if(d3dcaps.VS20Caps.NumTemps < VS2x_USE_MAXNUM_TEMP)
			{
				bSoftwareVertexProcessing = TRUE;
			}
#endif
		}
	}

	// 如果刚才是以硬件顶点创建设备的,而现在又需要强制软顶点以运行硬件不支持的VS,那么释放设备,重新创建
	if(bSoftwareVertexProcessing && UserVertexShaderProcessing == D3DCREATE_HARDWARE_VERTEXPROCESSING)
	{
		// 如果不支持指定版本的Vertex Shader,就强制创建软顶点处理设备
		sprintf(szErrorInfo, "警告:显卡不支持Vertex Shader %c.%c!强制以软件方式创建设备,性能会急剧下降!!!", pNeedVSVersion[3], pNeedVSVersion[5]);
		mymessage(szErrorInfo);
		SAFE_RELEASE(d3ddevice);
		hr = d3d->CreateDevice( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddevice);
		if(FAILED(hr))
		{
			char szErrorInfo[512] = "";
			sprintf(szErrorInfo, "创建D3D设备失败!请检查系统或硬件设置!比如显卡驱动程序或DirectX是否安装正确!错误号%x", hr);
			mymessage(szErrorInfo);
			return E_FAIL;
		}
	}

#endif



	//初始化摄像机,之所以放在这里,是为了设备丢失后不会又重置到初始位置
	D3DXVECTOR3 PtLookAt = g_PtCameraInitPos + g_VecCameraInitDir;
	CameraChange.InitCamera(g_PtCameraInitPos.x, g_PtCameraInitPos.y, g_PtCameraInitPos.z,  PtLookAt.x, PtLookAt.y, PtLookAt.z,  0.0f,1.0f,0.0f, 7,7,90);

	//得到硬件精确计时器的频率
	QueryPerformanceFrequency(&PerformanceFrequency);

	return S_OK;
}
Example #18
0
bool input_Init(HWND h)
{
    RECT rc;
    if (!GetWindowRect(h, &rc))
        return false;

    g_hwnd = h;

    SetCursorPos(rc.left, rc.top);

    HRESULT hr;
    DWORD   dwCoopFlags;
    if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION,
                                         IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
    {
        return false;
    }
    if( FAILED( hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL ) ) )
    {
        return false;
    }

    if( FAILED( hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL ) ) )
    {
        return false;
    }
    //Sets the data format for the Microsoft DirectInput device
    if( FAILED( hr = g_pMouse->SetDataFormat( &c_dfDIMouse ) ) )
    {
        return false;
    }
    if( FAILED( hr = g_pKeyboard->SetDataFormat( &c_dfDIKeyboard ) ) )
    {
        return false;
    }
///#define DINPUT_BUFFERSIZE 16
    DIPROPDWORD dipdw;
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    dipdw.diph.dwObj = 0;
    dipdw.diph.dwHow = DIPH_DEVICE;

    dipdw.dwData = DINPUT_BUFFERSIZE ;
    g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
    g_pKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
    /**
    	dipdw.dwData = DIPROPAXISMODE_ABS ;
        g_pMouse->SetProperty(DIPROP_AXISMODE, &dipdw.diph);
        **/
    //检测设备是否可以独占使用
    dwCoopFlags = DISCL_NONEXCLUSIVE|DISCL_BACKGROUND;
    //dwCoopFlags = DISCL_EXCLUSIVE|DISCL_BACKGROUND;
    hr = g_pMouse->SetCooperativeLevel( h, dwCoopFlags );
    if (DI_OK!=hr)
    {
        return false;
    }
    hr = g_pKeyboard->SetCooperativeLevel( h, dwCoopFlags );
    if (DI_OK!=hr)
    {
        return false;
    }
    //Obtains access to the input device.

    g_pMouse->Acquire();
    g_pKeyboard->Acquire();
    return true;
}
int Game_Main(void *parms, int num_parms)
{
// this is the workhorse of your game it will be called
// continuously in real-time this is like main() in C
// all the calls for you game go here!


int          index;             // looping var
int          dx,dy;             // general deltas used in collision detection
 
static int   player_moving = 0; // tracks player motion
static PALETTEENTRY glow = {0,0,0,PC_NOCOLLAPSE};  // used to animation red border
static int glow_count = 0, glow_dx = 5;

// check of user is trying to exit
if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
    PostMessage(main_window_handle, WM_DESTROY,0,0);

// start the timing clock
Start_Clock();

// clear the drawing surface
DDraw_Fill_Surface(lpddsback, 0);

// lock the back buffer
DDraw_Lock_Back_Surface();

// draw the background reactor image
Draw_Bitmap(&reactor, back_buffer, back_lpitch, 0);

// unlock the back buffer
DDraw_Unlock_Back_Surface();

// get player input

// get the keyboard data
lpdikey->GetDeviceState(256, (LPVOID)keyboard_state);

// reset motion flag
player_moving = 0;

// test direction of motion, this is a good example of testing the keyboard
// although the code could be optimized this is more educational

if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_UP]) 
   {
   // move skelaton
   skelaton.x+=2;
   skelaton.y-=2;
   dx=2; dy=-2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_NEAST)
      Set_Animation_BOB(&skelaton,SKELATON_NEAST);

   } // end if
else
if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_UP]) 
   {
   // move skelaton
   skelaton.x-=2;
   skelaton.y-=2;
   dx=-2; dy=-2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_NWEST)
      Set_Animation_BOB(&skelaton,SKELATON_NWEST);

   } // end if
else
if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_DOWN]) 
   {
   // move skelaton
   skelaton.x-=2;
   skelaton.y+=2;
   dx=-2; dy=2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_SWEST)
      Set_Animation_BOB(&skelaton,SKELATON_SWEST);

   } // end if
else
if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_DOWN]) 
   {
   // move skelaton
   skelaton.x+=2;
   skelaton.y+=2;
   dx=2; dy=2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_SEAST)
      Set_Animation_BOB(&skelaton,SKELATON_SEAST);

   } // end if
else
if (keyboard_state[DIK_RIGHT]) 
   {
   // move skelaton
   skelaton.x+=2;
   dx=2; dy=0;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_EAST)
      Set_Animation_BOB(&skelaton,SKELATON_EAST);

   } // end if
else
if (keyboard_state[DIK_LEFT])  
   {
   // move skelaton
   skelaton.x-=2;
   dx=-2; dy=0; 
   
   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_WEST)
      Set_Animation_BOB(&skelaton,SKELATON_WEST);

   } // end if
else
if (keyboard_state[DIK_UP])    
   {
   // move skelaton
   skelaton.y-=2;
   dx=0; dy=-2;
   
   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_NORTH)
      Set_Animation_BOB(&skelaton,SKELATON_NORTH);

   } // end if
else
if (keyboard_state[DIK_DOWN])  
   {
   // move skelaton
   skelaton.y+=2;
   dx=0; dy=+2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_SOUTH)
      Set_Animation_BOB(&skelaton,SKELATON_SOUTH);

   } // end if

// only animate if player is moving
if (player_moving)
   {
   // animate skelaton
   Animate_BOB(&skelaton);


   // see if skelaton hit a wall
   
   // lock surface, so we can scan it
   DDraw_Lock_Back_Surface();
   
   // call the color scanner with WALL_ANIMATION_COLOR, the color of the glowing wall
   // try to center the scan in the center of the object to make it 
   // more realistic
   if (Color_Scan(skelaton.x+16, skelaton.y+16,
                  skelaton.x+skelaton.width-16, skelaton.y+skelaton.height-16,                                    
                  WALL_ANIMATION_COLOR, WALL_ANIMATION_COLOR, back_buffer,back_lpitch))
      {
      // back the skelaton up along its last trajectory
      skelaton.x-=dx;
      skelaton.y-=dy;
      } // end if
   
   // done, so unlock
   DDraw_Unlock_Back_Surface();

   // check if skelaton is off screen
   if (skelaton.x < 0 || skelaton.x > (screen_width - skelaton.width))
      skelaton.x-=dx;

   if (skelaton.y < 0 || skelaton.y > (screen_height - skelaton.height))
      skelaton.y-=dy;

   } // end if

// draw the skelaton
Draw_BOB(&skelaton, lpddsback);

// animate color
glow.peGreen+=glow_dx;

// test boundary
if (glow.peGreen == 0 || glow.peGreen == 255)
   glow_dx = -glow_dx;

Set_Palette_Entry(WALL_ANIMATION_COLOR, &glow);

// draw some text
Draw_Text_GDI("I STILL HAVE A BONE TO PICK!",0,screen_height - 32,WALL_ANIMATION_COLOR,lpddsback);

Draw_Text_GDI("USE ARROW KEYS TO MOVE, <ESC> TO EXIT.",0,0,RGB(32,32,32),lpddsback);

// flip the surfaces
DDraw_Flip();

// sync to 30 fps
Wait_Clock(30);

// return success
return(1);

} // end Game_Main
int Game_Init(void *parms,  int num_parms)
{
// this function is where you do all the initialization 
// for your game

int index;         // looping var
char filename[80]; // used to build up files names

// start up DirectDraw (replace the parms as you desire)
DDraw_Init(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_BPP, WINDOWED_APP);

// joystick creation section ////////////////////////////////

// first create the direct input object
if (DirectInput8Create(main_instance,DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)&lpdi,NULL)!=DI_OK)
   return(0);

// first find the f*****g GUID of your particular joystick
lpdi->EnumDevices(DI8DEVCLASS_GAMECTRL, 
                  DI_Enum_Joysticks, 
                  &joystickGUID, 
                  DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK); 

if (lpdi->CreateDevice(joystickGUID, &lpdijoy, NULL)!=DI_OK)
   return(0);

// set cooperation level
if (lpdijoy->SetCooperativeLevel(main_window_handle, 
	                 DISCL_EXCLUSIVE | DISCL_BACKGROUND)!=DI_OK)
   return(0);

// set data format
if (lpdijoy->SetDataFormat(&c_dfDIJoystick2)!=DI_OK)
   return(0);

// set the range of the joystick
DIPROPRANGE joy_axis_range;

// first x axis
joy_axis_range.lMin = -32;
joy_axis_range.lMax = 32;

joy_axis_range.diph.dwSize       = sizeof(DIPROPRANGE); 
joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
joy_axis_range.diph.dwObj        = DIJOFS_X;
joy_axis_range.diph.dwHow        = DIPH_BYOFFSET;

lpdijoy->SetProperty(DIPROP_RANGE,&joy_axis_range.diph);

// now y-axis
joy_axis_range.lMin = -32;
joy_axis_range.lMax = 32;

joy_axis_range.diph.dwSize       = sizeof(DIPROPRANGE); 
joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
joy_axis_range.diph.dwObj        = DIJOFS_Y;
joy_axis_range.diph.dwHow        = DIPH_BYOFFSET;

lpdijoy->SetProperty(DIPROP_RANGE,&joy_axis_range.diph);

// and now the dead band

DIPROPDWORD dead_band; // here's our property word

dead_band.diph.dwSize       = sizeof(dead_band);
dead_band.diph.dwHeaderSize = sizeof(dead_band.diph);
dead_band.diph.dwObj        = DIJOFS_X;
dead_band.diph.dwHow        = DIPH_BYOFFSET;

// 4 will be used on both sides of the range +/-
dead_band.dwData            = 1000;

// finally set the property
lpdijoy->SetProperty(DIPROP_DEADZONE,&dead_band.diph);

dead_band.diph.dwSize       = sizeof(dead_band);
dead_band.diph.dwHeaderSize = sizeof(dead_band.diph);
dead_band.diph.dwObj        = DIJOFS_Y;
dead_band.diph.dwHow        = DIPH_BYOFFSET;

// 4 will be used on both sides of the range +/-
dead_band.dwData            = 1000;

// finally set the property
lpdijoy->SetProperty(DIPROP_DEADZONE,&dead_band.diph);


// acquire the joystick
if (lpdijoy->Acquire()!=DI_OK)
   return(0);


// force feedback setup
DWORD      dwAxes[2] = { DIJOFS_X, DIJOFS_Y };
LONG       lDirection[2] = { 0, 0 };


DIPERIODIC diPeriodic;      // type-specific parameters
DIENVELOPE diEnvelope;      // envelope
DIEFFECT   diEffect;        // general parameters

// setup the periodic structure
diPeriodic.dwMagnitude = DI_FFNOMINALMAX; 
diPeriodic.lOffset = 0; 
diPeriodic.dwPhase = 0; 
diPeriodic.dwPeriod = (DWORD) (0.05 * DI_SECONDS); 

// set the modulation envelope 
diEnvelope.dwSize = sizeof(DIENVELOPE);
diEnvelope.dwAttackLevel = 0; 
diEnvelope.dwAttackTime = (DWORD) (0.01 * DI_SECONDS); 
diEnvelope.dwFadeLevel = 0; 
diEnvelope.dwFadeTime = (DWORD) (3.0 * DI_SECONDS); 
 
// set up the effect structure itself
diEffect.dwSize = sizeof(DIEFFECT); 
diEffect.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS; 
diEffect.dwDuration = (DWORD) INFINITE; // (1 * DI_SECONDS);
 
// set up details of effect
diEffect.dwSamplePeriod = 0;               // = default 
diEffect.dwGain = DI_FFNOMINALMAX;         // no scaling
diEffect.dwTriggerButton = DIJOFS_BUTTON0; // connect effect to trigger button
diEffect.dwTriggerRepeatInterval = 0;      
diEffect.cAxes = 2; 
diEffect.rgdwAxes = dwAxes; 
diEffect.rglDirection = &lDirection[0]; 
diEffect.lpEnvelope = &diEnvelope; 
diEffect.cbTypeSpecificParams = sizeof(diPeriodic);
diEffect.lpvTypeSpecificParams = &diPeriodic;  
 
// create the effect and get the interface to it 
lpdijoy->CreateEffect(GUID_Square,  // standard GUID 
                     &diEffect,      // where the data is
                     &lpdieffect,    // where to put interface pointer
                     NULL);          // no aggregation


///////////////////////////////////////////////////////////

// load the background
Load_Bitmap_File(&bitmap16bit, "MUSH_24.BMP");

// load in the four frames of the mushroom
for (index=0; index<4; index++)
    {
    // create mushroom bitmaps
    Create_Bitmap(&mushrooms[index],0,0,32,32,16);
    Load_Image_Bitmap16(&mushrooms[index],&bitmap16bit,index,0,BITMAP_EXTRACT_MODE_CELL);  
    } // end for index

// now create the bug blaster bob
Create_BOB(&blaster,0,0,32,32,3,
           BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM | BOB_ATTR_ANIM_ONE_SHOT,
           DDSCAPS_SYSTEMMEMORY,0,16);

// load in the four frames of the mushroom
for (index=0; index<3; index++)
     Load_Frame_BOB16(&blaster,&bitmap16bit,index,index,1,BITMAP_EXTRACT_MODE_CELL);  

// unload the bitmap file
Unload_Bitmap_File(&bitmap16bit);

// set the animation sequences for bug blaster
Load_Animation_BOB(&blaster,0,5,blaster_anim);

// set up stating state of bug blaster
Set_Pos_BOB(&blaster,320, 400);
Set_Anim_Speed_BOB(&blaster,3);

// create mushroom playfield bitmap
Create_Bitmap(&playfield,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,16);
playfield.attr |= BITMAP_ATTR_LOADED;

// fill in the background
Load_Bitmap_File(&bitmap16bit, "GRASS_24.BMP");

// load the grass bitmap image
Load_Image_Bitmap16(&playfield,&bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
Unload_Bitmap_File(&bitmap16bit);

// seed random number generator
srand(Start_Clock());

// create the random mushroom patch
for (index=0; index<50; index++)
    {
    // select a mushroom
    int mush = rand()%4;

    // set mushroom to random position
    mushrooms[mush].x = rand()%(SCREEN_WIDTH-32);
    mushrooms[mush].y = rand()%(SCREEN_HEIGHT-128);

    // now draw the mushroom into playfield
    Draw_Bitmap16(&mushrooms[mush], playfield.buffer, playfield.width*2,1);

    } // end for

// hide the mouse
if (!WINDOWED_APP)
   ShowCursor(FALSE);

// return success
return(1);

} // end Game_Init
Example #21
0
//-----------------------------------------------------------------------------
// Name: UpdateInputState()
// Desc: Get the input device's state and display it.
//-----------------------------------------------------------------------------
HRESULT UpdateInputState( HWND hDlg )
{
    HRESULT hr;
    TCHAR strText[128] = {0}; // Device state text
    MouseState ms;           // Custom mouse state 

    static POINT pOrigin = {0};           // Initial position
    static BOOL bInitialized = FALSE;    // Indicates offsets are valid

    if( NULL == g_pMouse )
        return S_OK;

    // Poll the device to read the current state
    hr = g_pMouse->Poll();
    if( FAILED( hr ) )
    {
        // DInput is telling us that the input stream has been
        // interrupted. We aren't tracking any state between polls, so
        // we don't have any special reset that needs to be done. We
        // just re-acquire and try again.
        hr = g_pMouse->Acquire();
        while( hr == DIERR_INPUTLOST )
            hr = g_pMouse->Acquire();

        // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
        // may occur when the app is minimized or in the process of 
        // switching, so just try again later 
        return S_OK;
    }

    // Get the input's device state
    if( FAILED( hr = g_pMouse->GetDeviceState( sizeof( MouseState ), &ms ) ) )
        return hr; // The device should have been acquired during the Poll()

    // The initial mouse position should be subracted from the current point. 
    if( !bInitialized )
    {
        bInitialized = TRUE;
        pOrigin.x = ms.lAxisX;
        pOrigin.y = ms.lAxisY;
    }

    // Display state to dialog
    StringCchPrintf( strText, 128, TEXT( "%ld" ), ms.lAxisX - pOrigin.x );
    SetWindowText( GetDlgItem( hDlg, IDC_X_AXIS ), strText );
    StringCchPrintf( strText, 128, TEXT( "%ld" ), ms.lAxisY - pOrigin.y );
    SetWindowText( GetDlgItem( hDlg, IDC_Y_AXIS ), strText );

    // Fill up text with which buttons are pressed
    strText[0] = 0;
    for( int i = 0; i < 3; i++ )
    {
        if( ms.abButtons[i] & 0x80 )
        {
            TCHAR sz[128];
            StringCchPrintf( sz, 128, TEXT( "%02d " ), i );
            StringCchCat( strText, 128, sz );
        }
    }

    SetWindowText( GetDlgItem( hDlg, IDC_BUTTONS ), strText );

    return S_OK;
}
int Game_Main(void *parms, int num_parms)
{
// this is the workhorse of your game it will be called
// continuously in real-time this is like main() in C
// all the calls for you game go here!

int          index;             // looping var
int          dx,dy;             // general deltas used in collision detection


// check of user is trying to exit
if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
    PostMessage(main_window_handle, WM_DESTROY,0,0);

// start the timing clock
Start_Clock();

// clear the drawing surface
DDraw_Fill_Surface(lpddsback, 0);

// get joystick data
lpdijoy->Poll(); // this is needed for joysticks only
lpdijoy->GetDeviceState(sizeof(DIJOYSTATE2), (LPVOID)&joy_state);

// lock the back buffer
DDraw_Lock_Back_Surface();

// draw the background reactor image
Draw_Bitmap16(&playfield, back_buffer, back_lpitch, 0);

// unlock the back buffer
DDraw_Unlock_Back_Surface();

// is the player moving?
blaster.x+=joy_state.lX;
blaster.y+=joy_state.lY;

// test bounds
if (blaster.x > SCREEN_WIDTH-32)
    blaster.x = SCREEN_WIDTH-32;
else
if (blaster.x < 0)
    blaster.x = 0;

if (blaster.y > SCREEN_HEIGHT-32)
    blaster.y = SCREEN_HEIGHT-32;
else
if (blaster.y < SCREEN_HEIGHT-128)
    blaster.y = SCREEN_HEIGHT-128;

// is player firing?
if (joy_state.rgbButtons[0])
   Start_Missile();

// move and draw missle
Move_Missile();
Draw_Missile();

// is it time to blink eyes
if ((rand()%100)==50)
   Set_Animation_BOB(&blaster,0);

// draw blaster
Animate_BOB(&blaster);
Draw_BOB16(&blaster,lpddsback);

// draw some text
Draw_Text_GDI("(16-Bit Version) Let's Rock!!!",0,0,RGB(255,255,255),lpddsback);

// display joystick and buttons 0-7
sprintf(buffer,"Joystick Stats: X-Axis=%d, Y-Axis=%d, buttons(%d,%d,%d,%d,%d,%d,%d,%d)",
                                                                      joy_state.lX,joy_state.lY,
                                                                      joy_state.rgbButtons[0],
                                                                      joy_state.rgbButtons[1],
                                                                      joy_state.rgbButtons[2],
                                                                      joy_state.rgbButtons[3],
                                                                      joy_state.rgbButtons[4],
                                                                      joy_state.rgbButtons[5],
                                                                      joy_state.rgbButtons[6],
                                                                      joy_state.rgbButtons[7]);

Draw_Text_GDI(buffer,0,SCREEN_HEIGHT-20,RGB(255,255,50),lpddsback);

// print out name of joystick
sprintf(buffer, "Joystick Name & Vendor: %s",joyname);
Draw_Text_GDI(buffer,0,SCREEN_HEIGHT-40,RGB(255,255,50),lpddsback);


// flip the surfaces
DDraw_Flip();

// sync to 30 fps
Wait_Clock(30);

// return success
return(1);

} // end Game_Main
// This is the event dequeue & process function which updates
// Keyboard queue state. It can be called with 'blockingSinglepass'
// set to TRUE to process exactly one event, if called from the
// background keyboard queue processing thread. Alternatively it
// can be called synchronously from KbQueueCheck with a setting of FALSE
// to iterate over all available events and process them instantaneously:
void KbQueueProcessEvents(psych_bool blockingSinglepass)
{
    LPDIRECTINPUTDEVICE8 kb;
    DIDEVICEOBJECTDATA event;
    HRESULT rc;
    DWORD dwItems;
    double tnow;
    unsigned int i, keycode, keystate;
    PsychHIDEventRecord evt;
    WORD asciiValue[2];
    UCHAR keyboardState[256];

    while (1) {
        // Single pass or multi-pass?
        if (blockingSinglepass) {
            // Wait until at least one event available and dequeue it:
            // We use a timeout of 100 msecs.
            WaitForSingleObject(hEvent, 100);
        } else {
            // Check if event available, dequeue it, if so. Abort
            // processing if no new event available, aka queue empty:
            // TODO if (!XCheckTypedEvent(thread_dpy, GenericEvent, &KbQueue_xevent)) break;
        }

        // Take timestamp:
        PsychGetAdjustedPrecisionTimerSeconds(&tnow);

        // Need the lock from here on:
        PsychLockMutex(&KbQueueMutex);

        // Do a sweep over all keyboard devices whose queues are active:
        for (i = 0; i < (unsigned int) ndevices; i++) {
            // Skip this one if inactive:
            if (!psychHIDKbQueueActive[i]) continue;

            // Check this device:
            kb = GetXDevice(i);

            // Fetch one item from the buffer:
            // event.dwTimeStamp = Timestamp in msecs of timeGetTime() timebase.
            // event.dwSequence = Sequence number.

            // Fetch from this device, item-by-item, until nothing more to fetch:
            while (TRUE) {
                // Try one fetch from this device:
                dwItems = 1;
                rc = kb->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &event, &dwItems, 0);

                // If failed or nothing more to fetch, break out of fetch loop:
                if (!SUCCEEDED(rc) || (0 == dwItems)) break;

                // Clear ringbuffer event:
                memset(&evt, 0 , sizeof(evt));

                // Init character code to "unmapped": It will stay like that for anything but real keyboards:
                evt.cookedEventCode = -1;

                // Map to key code and key state:
                keycode = event.dwOfs & 0xff;
                keystate = event.dwData & 0x80;

                // Remap keycode into target slot in our arrays, depending on input device:
                switch (info[i].dwDevType & 0xff) {
                case DI8DEVTYPE_KEYBOARD:
                    // Try to map scancode to ascii character:
                    memset(keyboardState, 0, sizeof(keyboardState));
                    if (GetAsyncKeyState(VK_SHIFT)) keyboardState[VK_SHIFT] = 0xff;

                    if ((1 == ToAsciiEx(MapVirtualKeyEx(keycode, 1, GetKeyboardLayout(0)), keycode, keyboardState, (LPWORD) &(asciiValue[0]), 0, GetKeyboardLayout(0)))) {
                        // Mapped to single char: Return it as cooked keycode:
                        evt.cookedEventCode = (int) (asciiValue[0] & 0xff);
                    }
                    else {
                        // Could not map key to valid ascii character: Mark as "not mapped" aka zero:
                        evt.cookedEventCode = 0;
                    }

                    // Map scancode 'keycode' to virtual key code 'keycode':
                    keycode = PsychHIDOSMapKey(keycode);
                    break;

                case DI8DEVTYPE_MOUSE:
                case DI8DEVTYPE_SCREENPOINTER:
                    // Button event? Otherwise skip it.
                    if (keycode < 3 * sizeof(LONG)) continue;
                    // Correct for buttons offset in data structure DIMOUSESTATE2:
                    keycode -= 3 * sizeof(LONG);
                    break;

                case DI8DEVTYPE_JOYSTICK:
                    // Button event? Otherwise skip it.
                    if (keycode < (8 * sizeof(LONG) + 4 * sizeof(DWORD))) continue;
                    // Correct for buttons offset in data structure DIJOYSTATE2:
                    keycode -= (8 * sizeof(LONG) + 4 * sizeof(DWORD));
                    // Also skip if beyond button array:
                    if (keycode >= 128) continue;
                    break;

                default: // Unkown device -- Skip it.
                    continue;
                }

                // This keyboard queue interested in this keycode?
                if (psychHIDKbQueueScanKeys[i][keycode] != 0) {
                    // Yes: The queue wants to receive info about this key event.

                    // Press or release?
                    if (keystate) {
                        // Enqueue key press. Always in the "last press" array, because any
                        // press at this time is the best candidate for the last press.
                        // Only enqeue in "first press" if there wasn't any registered before,
                        // ie., the slot is so far empty:
                        if (psychHIDKbQueueFirstPress[i][keycode] == 0) psychHIDKbQueueFirstPress[i][keycode] = tnow;
                        psychHIDKbQueueLastPress[i][keycode] = tnow;
                        evt.status |= (1 << 0);
                    } else {
                        // Enqueue key release. See logic above:
                        if (psychHIDKbQueueFirstRelease[i][keycode] == 0) psychHIDKbQueueFirstRelease[i][keycode] = tnow;
                        psychHIDKbQueueLastRelease[i][keycode] = tnow;
                        evt.status &= ~(1 << 0);
                        // Clear cooked keycode - We don't record key releases this way:
                        if (evt.cookedEventCode > 0) evt.cookedEventCode = 0;
                    }

                    // Update event buffer:
                    evt.timestamp = tnow;
                    evt.rawEventCode = keycode + 1;
                    PsychHIDAddEventToEventBuffer(i, &evt);

                    // Tell waiting userspace (under KbQueueMutex protection for better scheduling) something interesting has changed:
                    PsychSignalCondition(&KbQueueCondition);
                }
                // Next fetch iteration for this device...
            }
            // Check next device...
        }

        // Done with shared data access:
        PsychUnlockMutex(&KbQueueMutex);

        // Done if we were only supposed to handle one sweep, which we did:
        if (blockingSinglepass) break;
    }

    return;
}
bool ForceFeedbackDevice::InitForceFeedback(const LPDIRECTINPUTDEVICE8 device, int axis_count)
{
  if (axis_count == 0)
    return false;

  // We just use the X axis (for wheel left/right).
  // Gamepads seem to not care which axis you use.
  // These are temporary for creating the effect:
  std::array<DWORD, 1> rgdwAxes = {DIJOFS_X};
  std::array<LONG, 1> rglDirection = {-200};

  DIEFFECT eff{};
  eff.dwSize = sizeof(eff);
  eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
  eff.dwDuration = DI_SECONDS / 1000 * RUMBLE_LENGTH_MS;
  eff.dwSamplePeriod = 0;
  eff.dwGain = DI_FFNOMINALMAX;
  eff.dwTriggerButton = DIEB_NOTRIGGER;
  eff.dwTriggerRepeatInterval = 0;
  eff.cAxes = DWORD(rgdwAxes.size());
  eff.rgdwAxes = rgdwAxes.data();
  eff.rglDirection = rglDirection.data();
  eff.dwStartDelay = 0;

  // Initialize parameters with zero force (their current state).
  DICONSTANTFORCE diCF{};
  diCF.lMagnitude = 0;
  DIRAMPFORCE diRF{};
  diRF.lStart = diRF.lEnd = 0;
  DIPERIODIC diPE{};
  diPE.dwMagnitude = 0;
  diPE.lOffset = 0;
  diPE.dwPhase = 0;
  diPE.dwPeriod = DI_SECONDS / 1000 * RUMBLE_PERIOD_MS;

  for (auto& f : force_type_names)
  {
    if (f.guid == GUID_ConstantForce)
    {
      eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
      eff.lpvTypeSpecificParams = &diCF;
    }
    else if (f.guid == GUID_RampForce)
    {
      eff.cbTypeSpecificParams = sizeof(DIRAMPFORCE);
      eff.lpvTypeSpecificParams = &diRF;
    }
    else
    {
      // All other forces need periodic parameters:
      eff.cbTypeSpecificParams = sizeof(DIPERIODIC);
      eff.lpvTypeSpecificParams = &diPE;
    }

    LPDIRECTINPUTEFFECT pEffect;
    if (SUCCEEDED(device->CreateEffect(f.guid, &eff, &pEffect, nullptr)))
    {
      if (f.guid == GUID_ConstantForce)
        AddOutput(new ForceConstant(this, f.name, pEffect, diCF));
      else if (f.guid == GUID_RampForce)
        AddOutput(new ForceRamp(this, f.name, pEffect, diRF));
      else
        AddOutput(new ForcePeriodic(this, f.name, pEffect, diPE));
    }
  }

  // Disable autocentering:
  if (Outputs().size())
  {
    DIPROPDWORD dipdw;
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    dipdw.diph.dwObj = 0;
    dipdw.diph.dwHow = DIPH_DEVICE;
    dipdw.dwData = DIPROPAUTOCENTER_OFF;
    device->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph);

    m_run_thread.Set();
    m_update_thread = std::thread(&ForceFeedbackDevice::ThreadFunc, this);
  }

  return true;
}
void PsychHIDOSKbQueueStart(int deviceIndex)
{
    LPDIRECTINPUTDEVICE8 kb;
    DIPROPDWORD  dipdw;
    psych_bool queueActive;
    int i;

    if (deviceIndex < 0) {
        deviceIndex = PsychHIDGetDefaultKbQueueDevice();
        // Ok, deviceIndex now contains our default keyboard to use - The first suitable keyboard.
    }

    if ((deviceIndex < 0) || (deviceIndex >= ndevices)) {
        // Out of range index:
        PsychErrorExitMsg(PsychError_user, "Invalid 'deviceIndex' specified. No such device!");
    }

    // Does Keyboard queue for this deviceIndex already exist?
    if (NULL == psychHIDKbQueueFirstPress[deviceIndex]) {
        // No. Bad bad...
        printf("PsychHID-ERROR: Tried to start processing on non-existent keyboard queue for deviceIndex %i! Call KbQueueCreate first!\n", deviceIndex);
        PsychErrorExitMsg(PsychError_user, "Invalid keyboard 'deviceIndex' specified. No queue for that device yet!");
    }

    // Keyboard queue already stopped? Then we ain't nothing to do:
    if (psychHIDKbQueueActive[deviceIndex]) return;

    // Queue is inactive. Start it:

    // Will this be the first active queue, ie., aren't there any queues running so far?
    queueActive = FALSE;
    for (i = 0; i < PSYCH_HID_MAX_DEVICES; i++) {
        queueActive |= psychHIDKbQueueActive[i];
    }

    PsychLockMutex(&KbQueueMutex);

    // Clear out current state for this queue:
    memset(psychHIDKbQueueFirstPress[deviceIndex]   , 0, (256 * sizeof(double)));
    memset(psychHIDKbQueueFirstRelease[deviceIndex] , 0, (256 * sizeof(double)));
    memset(psychHIDKbQueueLastPress[deviceIndex]    , 0, (256 * sizeof(double)));
    memset(psychHIDKbQueueLastRelease[deviceIndex]  , 0, (256 * sizeof(double)));

    // Setup event mask, so events from our associated xinput device
    // get enqueued in our event queue:
    kb = GetXDevice(deviceIndex);

    // Device specific data format setup:
    switch (info[deviceIndex].dwDevType & 0xff) {
    case DI8DEVTYPE_KEYBOARD:
        if (DI_OK != kb->SetDataFormat(&c_dfDIKeyboard)) {
            PsychUnlockMutex(&KbQueueMutex);
            printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting dataformat failed!\n", deviceIndex);
            PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!");
        }
        break;

    case DI8DEVTYPE_MOUSE:
    case DI8DEVTYPE_SCREENPOINTER:
        if (DI_OK != kb->SetDataFormat(&c_dfDIMouse2)) {
            PsychUnlockMutex(&KbQueueMutex);
            printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting dataformat failed!\n", deviceIndex);
            PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!");
        }
        break;

    case DI8DEVTYPE_JOYSTICK:
        if (DI_OK != kb->SetDataFormat(&c_dfDIJoystick2)) {
            PsychUnlockMutex(&KbQueueMutex);
            printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting dataformat failed!\n", deviceIndex);
            PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!");
        }
        break;
    }

    // Set device event buffer size to 256 elements:
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    dipdw.diph.dwObj = 0;
    dipdw.diph.dwHow = DIPH_DEVICE;
    dipdw.dwData = 256;

    if (DI_OK != kb->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) {
        PsychUnlockMutex(&KbQueueMutex);
        printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting buffersize on device failed!\n", deviceIndex);
        PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!");
    }

    // Enable state-change event notifications:
    if (DI_OK != kb->SetEventNotification(hEvent)) {
        PsychUnlockMutex(&KbQueueMutex);
        printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting device state notifications failed!\n", deviceIndex);
        PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!");
    }

    if (DI_OK != kb->Acquire()) {
        PsychUnlockMutex(&KbQueueMutex);
        printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but acquiring device failed!\n", deviceIndex);
        PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!");
    }

    // Mark this queue as logically started:
    psychHIDKbQueueActive[deviceIndex] = TRUE;

    // Queue started.
    PsychUnlockMutex(&KbQueueMutex);

    // If other queues are already active then we're done:
    if (queueActive) return;

    // No other active queues. We are the first one.

    // Start the common processing thread for all queues:
    PsychLockMutex(&KbQueueMutex);
    KbQueueThreadTerminate = FALSE;

    if (PsychCreateThread(&KbQueueThread, NULL, KbQueueWorkerThreadMain, NULL)) {
        // We are soo screwed:

        // Cleanup the mess:
        psychHIDKbQueueActive[deviceIndex] = FALSE;
        PsychUnlockMutex(&KbQueueMutex);

        // Whine a little bit:
        printf("PsychHID-ERROR: Start of keyboard queue processing failed!\n");
        PsychErrorExitMsg(PsychError_system, "Creation of keyboard queue background processing thread failed!");
    }

    // Up and running, we're done!
    PsychUnlockMutex(&KbQueueMutex);

    return;
}
Example #26
0
short pollKeyStates( unsigned short* modifierMask, unsigned short* modifierMask2 )
{
    static BYTE keystate[MAX_KEYS];    // create a static storage for the key-states
    
    dinKeyboard->Acquire();    // get access if we don't have it already
    
    HRESULT hr = dinKeyboard->GetDeviceState( MAX_KEYS, (LPVOID)keystate );    // fill keystate with values
    
    if ( ( ( (*modifierMask2) & LSHIFT_MASK2 ) != 0 ) && !( keystate[DIK_LSHIFT] & 0x80 ) )
	{
		(*modifierMask) = 0;
		return ( DIK_LSHIFT );
	}
	
    if ( ( ( (*modifierMask2) & RSHIFT_MASK2 ) != 0 ) && !( keystate[DIK_RSHIFT] & 0x80 ) )
	{
		(*modifierMask) = 0;
		return ( DIK_RSHIFT );
	}
	
    if ( ( ( (*modifierMask2) & LCTRL_MASK2 ) != 0 ) && !( keystate[DIK_LCONTROL] & 0x80 ) )
	{
		(*modifierMask) = 0;
		return ( DIK_LCONTROL );
	}
	
    if ( ( ( (*modifierMask2) & RCTRL_MASK2 ) != 0 ) && !( keystate[DIK_RCONTROL] & 0x80 ) )
	{
		(*modifierMask) = 0;
		return ( DIK_RCONTROL );
	}
	
    if ( ( ( (*modifierMask2) & ALT_MASK2 ) != 0 ) && !( keystate[DIK_LMENU] & 0x80 ) )
	{
		(*modifierMask) = 0;
		return ( DIK_LMENU );
	}
	
    if ( ( ( (*modifierMask2) & ALT_GR_MASK2 ) != 0 ) && !( keystate[DIK_RMENU] & 0x80 ) )
	{
		(*modifierMask) = 0;
		return ( DIK_RMENU );
	}
	
    if ( ( ( (*modifierMask2) & LMETA_MASK2 ) != 0 ) && !( keystate[DIK_LWIN] & 0x80 ) )
	{
		(*modifierMask) = 0;
		return ( DIK_LWIN );
	}
	
    if ( ( ( (*modifierMask2) & RMETA_MASK2 ) != 0 ) && !( keystate[DIK_RWIN] & 0x80 ) )
	{
		(*modifierMask) = 0;
		return ( DIK_RWIN );
	}
	
	BYTE* ss = keystate;
	short result = -1;
    for ( unsigned short i = 0; i < numKeys; i++ )
    {
        if ( *ss++ & 0x80 )
        {
			switch ( i )
			{
				case DIK_LSHIFT:
					(*modifierMask) |= SHIFT_MASK;
					(*modifierMask2) |= LSHIFT_MASK2;
					break;
				case DIK_RSHIFT:
					(*modifierMask) |= SHIFT_MASK;
					(*modifierMask2) |= RSHIFT_MASK2;
					break;
				case DIK_LCONTROL:
					(*modifierMask) |= CTRL_MASK;
					(*modifierMask2) |= LCTRL_MASK2;
					break;
				case DIK_RCONTROL:
					(*modifierMask) |= CTRL_MASK;
					(*modifierMask2) |= RCTRL_MASK2;
					break;
				case DIK_LMENU:
					(*modifierMask) |= ALT_MASK;
					(*modifierMask2) |= ALT_MASK2;
					break;
				case DIK_RMENU:
					(*modifierMask) |= ALT_GR_MASK;
					(*modifierMask2) |= ALT_GR_MASK2;
					break;
				case DIK_LWIN:
					(*modifierMask) |= LMETA_MASK;
					(*modifierMask2) |= LMETA_MASK2;
					break;
				case DIK_RWIN:
					(*modifierMask) |= RMETA_MASK;
					(*modifierMask2) |= RMETA_MASK2;
					break;
				default:
					result = (short)i;
					break;
			}
        }
    }
    
	return ( result );
}
Example #27
0
    HRESULT InitDirectInput(unsigned int joystick_index)
    {
        HRESULT hr;

        state.is_initialized = false;

        // Register with the DirectInput subsystem and get a pointer
        // to a IDirectInput interface we can use.
        // Create a DInput object
        if (FAILED(hr = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION,
            IID_IDirectInput8, (VOID**)&g_pDI, nullptr)))
            return hr;


        if (g_bFilterOutXinputDevices)
            SetupForIsXInputDevice();

        enumContext.pPreferredJoyCfg = &PreferredJoyCfg;
        enumContext.bPreferredJoyCfgValid = false;

        IDirectInputJoyConfig8* pJoyConfig = nullptr;
        if (FAILED(hr = g_pDI->QueryInterface(IID_IDirectInputJoyConfig8, (void**)&pJoyConfig))) {
            state.message = "QueryInterface on IID_IDirectInputJoyConfig8 failed";
            return hr;
        }

        PreferredJoyCfg.dwSize = sizeof(PreferredJoyCfg);
        if (SUCCEEDED(pJoyConfig->GetConfig(joystick_index, &PreferredJoyCfg, DIJC_GUIDINSTANCE))) { // This function is expected to fail if no joystick is attached
            enumContext.bPreferredJoyCfgValid = true;

            joystick_info.is_valid = true;
            joystick_info.instance_guide = toDIGUID(PreferredJoyCfg.guidInstance);
            joystick_info.pid_vid = toString(PreferredJoyCfg.wszType);
        }
        DIJT_SAFE_RELEASE(pJoyConfig);

        // Look for a simple joystick we can use for this sample program.
        if (FAILED(hr = g_pDI->EnumDevices(DI8DEVCLASS_GAMECTRL,
            DirectInputJoyStick::impl::EnumJoysticksCallback,
            this, DIEDFL_ATTACHEDONLY))) {

            state.message = "EnumDevices failed";
            return hr;
        }

        if (g_bFilterOutXinputDevices)
            CleanupForIsXInputDevice();

        // Make sure we got a joystick
        if (!g_pJoystick)
        {
            state.message = "Joystick at index " + std::to_string(joystick_index) + " is not available";
            return S_FALSE;
        }

        // 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 DInput that we will be
        // passing a DIJOYSTATE2 structure to IDirectInputDevice::GetDeviceState().
        if (FAILED(hr = g_pJoystick->SetDataFormat(&c_dfDIJoystick2)))
        {
            state.message = "Device does not support DIJOYSTATE2";
            return hr;
        }

        // Set the cooperative level to let DInput know how this device should
        // interact with the system and with other DInput applications.
        if (FAILED(hr = g_pJoystick->SetCooperativeLevel(NULL, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) {

            state.message = "SetCooperativeLevel failed";
            return hr;
        }

        // Enumerate the joystick objects. The callback function enabled user
        // interface elements for objects that are found, and sets the min/max
        // values property for discovered axes.
        if (FAILED(hr = g_pJoystick->EnumObjects(DirectInputJoyStick::impl::EnumObjectsCallback,
            (VOID*) this, DIDFT_ALL))) {

            state.message = "EnumObjects failed";
            return hr;
        }

        InitForceFeedback();

        state.is_initialized = true;
        return S_OK;
    }
Example #28
0
//-----------------------------------------------------------------------------
// Name: OnMouseInput()
// Desc: Handles responding to any mouse input that is generated from
//       the mouse event being triggered.
//-----------------------------------------------------------------------------
VOID OnMouseInput( HWND hWnd )
{
    BOOL                bDone;
    DIDEVICEOBJECTDATA  od;
    DWORD               dwElements;
    HRESULT             hr;

    // Invalidate the old cursor so it will be erased 
    InvalidateCursorRect( hWnd );

    // Attempt to read one data element.  Continue as long as
    // device data is available.
    bDone = FALSE;
    while( !bDone ) 
    {
        dwElements = 1;
        hr = g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), 
                                      &od, &dwElements, 0 );

        if( hr == DIERR_INPUTLOST ) 
        {
            SetAcquire();
            break;
        }

        // Unable to read data or no data available
        if( FAILED(hr) || dwElements == 0 ) 
        {
            break;
        }

        // Look at the element to see what happened
        switch( od.dwOfs ) 
        {     
            case DIMOFS_X:       // Mouse horizontal motion 
                UpdateCursorPosition( od.dwData, 0 ); 
                break;

            case DIMOFS_Y:       // Mouse vertical motion 
                UpdateCursorPosition( 0, od.dwData ); 
                break;

            case DIMOFS_BUTTON0: // Right button pressed or released 
            case DIMOFS_BUTTON1: // Left button pressed or released 
                // Is the right or a swapped left button down?
                if( ( g_bSwapMouseButtons  && DIMOFS_BUTTON1 == od.dwOfs ) ||
                    ( !g_bSwapMouseButtons && DIMOFS_BUTTON0 == od.dwOfs ) )
                {
                    if( od.dwData & 0x80 ) 
                    { 
                        // left button pressed, so go into button-down mode 
                        bDone = TRUE;
                        OnLeftButtonDown( hWnd ); 
                    }
                }

                // is the left or a swapped right button down?
                if( ( g_bSwapMouseButtons  && DIMOFS_BUTTON0 == od.dwOfs ) ||
                    ( !g_bSwapMouseButtons && DIMOFS_BUTTON1 == od.dwOfs ) )
                {
                    if( !(od.dwData & 0x80) ) 
                    {  
                        // button released, so check context menu 
                        bDone = TRUE;
                        OnRightButtonUp( hWnd ); 
                    }
                }
                break;
        }
    }

    // Invalidate the new cursor so it will be drawn 
    InvalidateCursorRect( hWnd );
}
Example #29
0
static unsigned long Update(void *device)
{
	// Poll the device to read the current state
	if (!g_pJoystick)
		return -1;

    HRESULT hr = g_pJoystick->Poll();
    if(FAILED(hr))
    {
        // DInput is telling us that the input stream has been
        // interrupted. We aren't tracking any state between polls, so
        // we don't have any special reset that needs to be done. We
        // just re-acquire and try again.
        hr = SYS_DXTRACE(g_pJoystick->Acquire());
        while( hr == DIERR_INPUTLOST )
            hr = SYS_DXTRACE(g_pJoystick->Acquire());

        // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
        // may occur when the app is minimized or in the process of
        // switching, so just try again later
        return S_OK;
    }

    // Get the input's device state
    if( FAILED( hr = SYS_DXTRACE(g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &g_sJOY ) ) ) )
        return hr; // The device should have been acquired during the Poll()

    sJOY->lX = g_sJOY.lX;
	sJOY->lY = g_sJOY.lY;
	sJOY->lZ = g_sJOY.lZ;
	sJOY->lRx = g_sJOY.lRx;
	sJOY->lRy = g_sJOY.lRy;
	sJOY->lRz = g_sJOY.lRz;

// TODO:  lRx = lZ and lRy = lRx with PS2 pad

	sJOY->rglSlider[0] = sJOY->rglSlider[0];
	sJOY->rglSlider[1] = sJOY->rglSlider[1];
	sysMemCpy(sJOY->rgdwPOV, g_sJOY.rgdwPOV, 4 * 4);
	sysMemCpy(sJOY->steButtons, sJOY->rgbButtons, 128);
	sysMemCpy(sJOY->rgbButtons, g_sJOY.rgbButtons, 128);

#if DIRECTINPUT_VERSION >=0x0700
	sJOY->lVX = g_sJOY.lVX;
	sJOY->lVY = g_sJOY.lVY;
	sJOY->lVZ = g_sJOY.lVZ;
	sJOY->lVRx = g_sJOY.lVRx;
	sJOY->lVRy = g_sJOY.lVRy;
	sJOY->lVRz = g_sJOY.lVRz;
	sJOY->rglVSlider[0] = g_sJOY.rglVSlider[0];
	sJOY->rglVSlider[1] = g_sJOY.rglVSlider[1];
	sJOY->lAX = g_sJOY.lAX;
	sJOY->lAY = g_sJOY.lAY;
	sJOY->lAZ = g_sJOY.lAZ;
	sJOY->lARx = g_sJOY.lARx;
	sJOY->lARy = g_sJOY.lARy;
	sJOY->lARz = g_sJOY.lARz;
	sJOY->rglASlider[0] = g_sJOY.rglASlider[0];
	sJOY->rglASlider[1] = g_sJOY.rglASlider[1];
	sJOY->lFX = g_sJOY.lFX;
	sJOY->lFY = g_sJOY.lFY;
	sJOY->lFZ = g_sJOY.lFZ;
	sJOY->lFRx = g_sJOY.lFRx;
	sJOY->lFRy = g_sJOY.lFRy;
	sJOY->lFRz = g_sJOY.lFRz;
	sJOY->rglFSlider[0] = g_sJOY.rglFSlider[0];
	sJOY->rglFSlider[1] = g_sJOY.rglFSlider[1];
#endif
	return 0;
}
Example #30
0
BOOL CALLBACK enumCallback(const DIDEVICEINSTANCE* instance, VOID* context) {
	HRESULT hr;
	BOOL xinput = false;

	if (instance->wUsagePage != 1 || instance->wUsage != 5) {
		// Not an actual game controller (see issue #3)
		return DIENUM_CONTINUE;
	}

	// First check if the device is known
	auto it = isXInput.find(instance->guidInstance);
	if (it == isXInput.end()) {
		// Not found yet, so check if it is an XInputDevice
		xinput = isXInputDevice(&instance->guidProduct);
		isXInput[instance->guidInstance] = xinput;
	} else {
		xinput = it->second;
	}

	if (xinput) {
		// If it is an xinput, we can safely ignore
		return DIENUM_CONTINUE;
	}

	// Check if we have a live DI instance of this joystick
	if (joysticks.find(instance->guidInstance) != joysticks.end()) {
		return DIENUM_CONTINUE;
	}

	// If not we must build it...

	LPDIRECTINPUTDEVICE8 joystick;
	// Obtain an interface to the enumerated joystick.
	hr = di->CreateDevice(instance->guidInstance, &joystick, NULL);
	// If it failed, then we can't use this joystick. (Maybe the user unplugged
	// it while we were in the middle of enumerating it.)
	if (FAILED(hr)) {
		// As seen on x360ce, if create device fails on guid instance, try the product
		hr = di->CreateDevice(instance->guidProduct, &joystick, NULL);
		if (FAILED(hr))
			return DIENUM_CONTINUE;
	}

	// 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 DInput that we will be
	// passing a DIJOYSTATE2 structure to IDirectInputDevice::GetDeviceState().
	if (FAILED(hr = joystick->SetDataFormat(&c_dfDIJoystick2))) {
		printf("SetDataFormat is f****d %x\n", hr);
		joystick->Release();
		return DIENUM_CONTINUE;
	}

	hr = joystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND);
	if (FAILED(hr)) {
		hr = joystick->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
		if (FAILED(hr)) {
			printf("Cooperative is f****d %x\n", hr);
		}
	}

	DIPROPDWORD dipdw;
	dipdw.diph.dwSize = sizeof(DIPROPDWORD);
	dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
	dipdw.diph.dwObj = 0;
	dipdw.diph.dwHow = DIPH_DEVICE;
	dipdw.dwData = DIPROPAUTOCENTER_ON;
	joystick->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph);

	// Acquire the device
	if (FAILED(hr = joystick->Acquire())) {
		printf("Acquire is f****d %x\n", hr);
		joystick->Release();
		return DIENUM_CONTINUE;
	}

	// Store the joystick instance accessible via guid
	joysticks[instance->guidInstance] = joystick;

	// Get other devices
	return DIENUM_CONTINUE;
}