mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
Dynamically load xinput
This commit is contained in:
parent
3b0d8b1efb
commit
630edadf9c
@ -46,7 +46,6 @@ function maintargetosdoptions(_target,_subtarget)
|
||||
"comctl32",
|
||||
"comdlg32",
|
||||
"psapi",
|
||||
"xinput",
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -116,6 +116,107 @@ struct xinput_api_state
|
||||
XINPUT_CAPABILITIES caps;
|
||||
};
|
||||
|
||||
// Typedef for pointers to XInput Functions
|
||||
typedef DWORD(__stdcall* PFN_XINPUTGETSTATE)(DWORD, XINPUT_STATE*);
|
||||
typedef DWORD(__stdcall* PFN_XINPUTGETCAPS)(DWORD, DWORD, XINPUT_CAPABILITIES*);
|
||||
|
||||
class xinput_interface
|
||||
{
|
||||
private:
|
||||
HMODULE m_xinput_module;
|
||||
PFN_XINPUTGETSTATE m_pfnXInputGetState;
|
||||
PFN_XINPUTGETCAPS m_pfnXInputGetCapabilities;
|
||||
bool m_initialized;
|
||||
|
||||
xinput_interface()
|
||||
: m_xinput_module(NULL),
|
||||
m_pfnXInputGetState(nullptr),
|
||||
m_pfnXInputGetCapabilities(nullptr),
|
||||
m_initialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
int initialize()
|
||||
{
|
||||
if (m_initialized)
|
||||
return 0;
|
||||
|
||||
m_xinput_module = load_xinput_library();
|
||||
if (m_xinput_module == NULL)
|
||||
{
|
||||
osd_printf_error("Failed to load xinput library. Error: %u\n", (unsigned int)GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (load_xinput_exports() != 0)
|
||||
{
|
||||
osd_printf_error("Failed to load exported XInput functions from library\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD load_xinput_exports()
|
||||
{
|
||||
m_pfnXInputGetState = (PFN_XINPUTGETSTATE)GetProcAddress(m_xinput_module, "XInputGetState");
|
||||
m_pfnXInputGetCapabilities = (PFN_XINPUTGETCAPS)GetProcAddress(m_xinput_module, "XInputGetCapabilities");
|
||||
|
||||
if (m_pfnXInputGetState == nullptr
|
||||
|| m_pfnXInputGetCapabilities == nullptr)
|
||||
{
|
||||
return ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HMODULE load_xinput_library()
|
||||
{
|
||||
// Attempt to load the Windows 8/10 version of Xinput first
|
||||
HMODULE module = LoadLibrary(L"xinput1_4.dll");
|
||||
|
||||
// Fall back to the one from DX SDK
|
||||
if (module == NULL)
|
||||
{
|
||||
module = LoadLibrary(L"xinput9_1_0.dll");
|
||||
}
|
||||
|
||||
// If we still didn't load it, fail
|
||||
if (module == NULL)
|
||||
{
|
||||
osd_printf_warning("Could not load any verions of the XInput Library.\n");
|
||||
SetLastError(ERROR_DLL_NOT_FOUND);
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
public:
|
||||
inline DWORD XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState)
|
||||
{
|
||||
return m_pfnXInputGetState(dwUserIndex, pState);
|
||||
}
|
||||
|
||||
inline DWORD XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
|
||||
{
|
||||
return m_pfnXInputGetCapabilities(dwUserIndex, dwFlags, pCapabilities);
|
||||
}
|
||||
|
||||
static DWORD get_interface(xinput_interface **ppinterface)
|
||||
{
|
||||
static xinput_interface s_instance;
|
||||
DWORD error = s_instance.initialize();
|
||||
if (error == 0)
|
||||
{
|
||||
*ppinterface = &s_instance;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================
|
||||
// xinput_joystick_device
|
||||
//============================================================
|
||||
@ -126,17 +227,28 @@ public:
|
||||
gamepad_state gamepad;
|
||||
xinput_api_state xinput_state;
|
||||
|
||||
private:
|
||||
xinput_interface* xinput_api;
|
||||
|
||||
public:
|
||||
xinput_joystick_device(running_machine &machine, const char *name, input_module &module)
|
||||
: device_info(machine, name, DEVICE_CLASS_JOYSTICK, module),
|
||||
gamepad({0}),
|
||||
xinput_state({0})
|
||||
{
|
||||
// Attempt to get the xinput interface
|
||||
xinput_api = nullptr;
|
||||
xinput_interface::get_interface(&xinput_api);
|
||||
}
|
||||
|
||||
void poll() override
|
||||
{
|
||||
// Nothing we can do if for some reason the API couldn't be loaded
|
||||
if (xinput_api == nullptr)
|
||||
return;
|
||||
|
||||
// poll the device first
|
||||
HRESULT result = XInputGetState(xinput_state.playerIndex, &xinput_state.xstate);
|
||||
HRESULT result = xinput_api->XInputGetState(xinput_state.playerIndex, &xinput_state.xstate);
|
||||
|
||||
// If we can't poll the device, skip
|
||||
if (FAILED(result))
|
||||
@ -182,15 +294,40 @@ public:
|
||||
|
||||
class xinput_joystick_module : public wininput_module
|
||||
{
|
||||
private:
|
||||
xinput_interface* xinput_api;
|
||||
|
||||
public:
|
||||
xinput_joystick_module()
|
||||
: wininput_module(OSD_JOYSTICKINPUT_PROVIDER, "xinput")
|
||||
: wininput_module(OSD_JOYSTICKINPUT_PROVIDER, "xinput"),
|
||||
xinput_api(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
int init(const osd_options &options) override
|
||||
{
|
||||
// Call the base
|
||||
int status = wininput_module::init(options);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
// Make sure we can get the xinput API
|
||||
status = xinput_interface::get_interface(&xinput_api);
|
||||
if (status != 0)
|
||||
{
|
||||
osd_printf_error("xinput_joystick_module failed to get XInput interface! Error: %u\n", (unsigned int)status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void input_init(running_machine &machine) override
|
||||
{
|
||||
// The Xinput API should have been obtained already
|
||||
assert(xinput_api != nullptr);
|
||||
|
||||
xinput_joystick_device *devinfo;
|
||||
|
||||
// Loop through each gamepad to determine if they are connected
|
||||
@ -198,7 +335,7 @@ protected:
|
||||
{
|
||||
XINPUT_STATE state = {0};
|
||||
|
||||
if (XInputGetState(i, &state) == ERROR_SUCCESS)
|
||||
if (xinput_api->XInputGetState(i, &state) == ERROR_SUCCESS)
|
||||
{
|
||||
// allocate and link in a new device
|
||||
devinfo = create_xinput_device(machine, i);
|
||||
@ -261,7 +398,7 @@ protected:
|
||||
xinput_joystick_device *devinfo;
|
||||
|
||||
XINPUT_CAPABILITIES caps = {0};
|
||||
if (FAILED(XInputGetCapabilities(index, 0, &caps)))
|
||||
if (FAILED(xinput_api->XInputGetCapabilities(index, 0, &caps)))
|
||||
{
|
||||
// If we can't get the capabilities skip this device
|
||||
return nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user