Supermodel/Src/OSD/Windows/DirectInputSystem.h
Nik Henson e8782b98fa Changes relating to input system:
- Added ability to configure axis min, centre and max values in INI file.  This allows some types of steering wheel pedals that use an inverted value range to work properly with the emulator.
 - Modified CINIFile to read and write signed numbers (needed for above change).
 - Added check at configuration start for "bad" input sources such as axes that are wrongly calibrated or buttons that are always triggering a value.  Otherwise they cause the configuration loop to wait indefinitely for the axis or button to be released.
 - Removed superfluous check for XInput devices when XInput is not enabled in CDirectInputSystem.
 - Improved force beedback code in CDirectInputSystem and also added the extra feedback effects needed so far for drive board emulation.
2011-06-22 13:06:52 +00:00

234 lines
6.7 KiB
C++

#ifndef INCLUDED_DIRECTINPUTSYSTEM_H
#define INCLUDED_DIRECTINPUTSYSTEM_H
#include "Types.h"
#include "Inputs/Input.h"
#include "Inputs/InputSource.h"
#include "Inputs/InputSystem.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <dinput.h>
#include <XInput.h>
#include <vector>
using namespace std;
#define NUM_DI_KEYS (sizeof(s_keyMap) / sizeof(DIKeyMapStruct))
struct DIKeyMapStruct
{
const char *keyName;
int diKey;
};
struct RawMseState
{
LONG x;
LONG y;
LONG z;
LONG wheelDelta;
SHORT wheelDir;
USHORT buttons;
};
struct DIMseState
{
LONG x;
LONG y;
LONG z;
SHORT wheelDir;
BYTE buttons[5];
};
struct DIJoyInfo
{
GUID guid;
bool isXInput;
int dInputNum;
LPDIRECTINPUTEFFECT dInputEffects[NUM_JOY_AXES][NUM_FF_EFFECTS];
int xInputNum;
};
struct DIEnumDevsContext
{
vector<DIJoyInfo> *infos;
bool useXInput;
};
// RawInput API
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDeviceListPtr)(OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PUINT puiNumDevices, IN UINT cbSize);
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDeviceInfoPtr)(IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize);
typedef /*WINUSERAPI*/ BOOL (WINAPI *RegisterRawInputDevicesPtr)(IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize);
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDataPtr)(IN HRAWINPUT hRawInput, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize, IN UINT cbSizeHeader);
// XInput API
typedef /*WINUSERAPI*/ DWORD (WINAPI *XInputGetCapabilitiesPtr)(IN DWORD dwUserIndex, IN DWORD dwFlags, OUT PXINPUT_CAPABILITIES pCapabilities);
typedef /*WINUSERAPI*/ DWORD (WINAPI *XInputGetStatePtr)(IN DWORD dwUserIndex, OUT PXINPUT_STATE pState);
typedef /*WINUSERAPI*/ DWORD (WINAPI *XInputSetStatePtr)(IN DWORD dwUserIndex, IN PXINPUT_VIBRATION pVibration);
// DirectInput callbacks
static bool IsXInputDevice(const GUID &devProdGUID);
static BOOL CALLBACK DI8EnumDevicesCallback(LPCDIDEVICEINSTANCE instance, LPVOID context);
static BOOL CALLBACK DI8EnumAxesCallback(LPDIDEVICEOBJECTINSTANCE instance, LPVOID context);
static BOOL CALLBACK DI8EnumEffectsCallback(LPCDIEFFECTINFO effectInfo, LPVOID context);
/*
* Input system that uses combination of DirectInput, XInput and RawInput APIs.
*/
class CDirectInputSystem : public CInputSystem
{
private:
// Lookup table to map key names to DirectInput keycodes and Virtual keycodes
static DIKeyMapStruct s_keyMap[];
static const char *ConstructName(bool useRawInput, bool useXInput, bool enableFFeedback);
bool m_useRawInput;
bool m_useXInput;
bool m_enableFFeedback;
HWND m_hwnd;
DWORD m_screenW;
DWORD m_screenH;
bool m_activated;
// Function pointers for RawInput API
GetRawInputDeviceListPtr m_getRIDevListPtr;
GetRawInputDeviceInfoPtr m_getRIDevInfoPtr;
RegisterRawInputDevicesPtr m_regRIDevsPtr;
GetRawInputDataPtr m_getRIDataPtr;
// Keyboard, mouse and joystick details
vector<KeyDetails> m_keyDetails;
vector<MouseDetails> m_mseDetails;
vector<JoyDetails> m_joyDetails;
// RawInput keyboard and mice handles and states
vector<HANDLE> m_rawKeyboards;
vector<BOOL*> m_rawKeyStates;
vector<HANDLE> m_rawMice;
RawMseState m_combRawMseState;
vector<RawMseState> m_rawMseStates;
// Function pointers for XInput API
XInputGetCapabilitiesPtr m_xiGetCapabilitiesPtr;
XInputGetStatePtr m_xiGetStatePtr;
XInputSetStatePtr m_xiSetStatePtr;
// DirectInput pointers and details
LPDIRECTINPUT8 m_di8;
LPDIRECTINPUTDEVICE8 m_di8Keyboard;
LPDIRECTINPUTDEVICE8 m_di8Mouse;
vector<LPDIRECTINPUTDEVICE8> m_di8Joysticks;
// DirectInput keyboard and mouse states
BYTE m_diKeyState[256];
DIMseState m_diMseState;
// DirectInput joystick infos and states
vector<DIJoyInfo> m_diJoyInfos;
vector<DIJOYSTATE2> m_diJoyStates;
bool GetRegString(HKEY regKey, const char *regPath, string &str);
bool GetRegDeviceName(const char *rawDevName, char *name);
void OpenKeyboardsAndMice();
void ActivateKeyboardsAndMice();
void PollKeyboardsAndMice();
void CloseKeyboardsAndMice();
void ResetMice();
void ProcessRawInput(HRAWINPUT hInput);
void OpenJoysticks();
void ActivateJoysticks();
void PollJoysticks();
void CloseJoysticks();
HRESULT CreateJoystickEffect(LPDIRECTINPUTDEVICE8 di8Joystick, int axisNum, ForceFeedbackCmd ffCmd, LPDIRECTINPUTEFFECT *di8Effect);
protected:
/*
* Initializes the DirectInput input system.
*/
bool InitializeSystem();
int GetKeyIndex(const char *keyName);
const char *GetKeyName(int keyIndex);
bool IsKeyPressed(int joyNum, int keyIndex);
int GetMouseAxisValue(int mseNum, int axisNum);
int GetMouseWheelDir(int mseNum);
bool IsMouseButPressed(int mseNum, int butNum);
int GetJoyAxisValue(int joyNum, int axisNum);
bool IsJoyPOVInDir(int joyNum, int povNum, int povDir);
bool IsJoyButPressed(int joyNum, int butNum);
bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd);
void Wait(int ms);
bool ConfigMouseCentered();
CInputSource *CreateAnyMouseSource(EMousePart msePart);
public:
/*
* Constructs a DirectInput/XInput/RawInput input system.
* If useRawInput is true then RawInput is used for keyboard and mice movements (allowing multiple devices, eg for dual lightguns in gun
* games such as Lost World). If false then DirectInput is used instead (which doesn't allow multiple devices). In both cases,
* DirectInput/XInput is used for reading joysticks.
* If useXInput is true then XInput is used for reading XBox 360 game controllers (and/or XInput compatible joysticks) and DirectInput is used
* for all other types of joystick. If false, then DirectInput is used for reading all joysticks (including XBox 360 ones).
* The advantage of using XInput for XBox 360 game controllers is that it allows the left and right triggers to be used simultaneously
* (ie to brake and accelerate at the same time in order to power slide the car in Daytona USA 2). Under DirectInput the triggers get mapped
* to the same shared axis and so cannot be distinguished when pressed together.
* If enableFFeedback is true then force feedback is enabled (for those joysticks which are force feedback capable).
*/
CDirectInputSystem(bool useRawInput, bool useXInput, bool enableFFeedback);
~CDirectInputSystem();
int GetNumKeyboards();
int GetNumMice();
int GetNumJoysticks();
const KeyDetails *GetKeyDetails(int kbdNum);
const MouseDetails *GetMouseDetails(int mseNum);
const JoyDetails *GetJoyDetails(int joyNum);
bool Poll();
void GrabMouse();
void UngrabMouse();
void SetMouseVisibility(bool visible);
};
#endif // INCLUDED_DIRECTINPUTSYSTEM_H