mirror of
https://github.com/holub/mame
synced 2025-06-07 05:13:46 +03:00
Merge dynamic load XInput
This commit is contained in:
commit
65c3b22b20
@ -46,7 +46,6 @@ function maintargetosdoptions(_target,_subtarget)
|
|||||||
"comctl32",
|
"comctl32",
|
||||||
"comdlg32",
|
"comdlg32",
|
||||||
"psapi",
|
"psapi",
|
||||||
"xinput",
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -116,6 +116,107 @@ struct xinput_api_state
|
|||||||
XINPUT_CAPABILITIES caps;
|
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
|
// xinput_joystick_device
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -126,17 +227,28 @@ public:
|
|||||||
gamepad_state gamepad;
|
gamepad_state gamepad;
|
||||||
xinput_api_state xinput_state;
|
xinput_api_state xinput_state;
|
||||||
|
|
||||||
|
private:
|
||||||
|
xinput_interface* xinput_api;
|
||||||
|
|
||||||
|
public:
|
||||||
xinput_joystick_device(running_machine &machine, const char *name, input_module &module)
|
xinput_joystick_device(running_machine &machine, const char *name, input_module &module)
|
||||||
: device_info(machine, name, DEVICE_CLASS_JOYSTICK, module),
|
: device_info(machine, name, DEVICE_CLASS_JOYSTICK, module),
|
||||||
gamepad({0}),
|
gamepad({0}),
|
||||||
xinput_state({0})
|
xinput_state({0})
|
||||||
{
|
{
|
||||||
|
// Attempt to get the xinput interface
|
||||||
|
xinput_api = nullptr;
|
||||||
|
xinput_interface::get_interface(&xinput_api);
|
||||||
}
|
}
|
||||||
|
|
||||||
void poll() override
|
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
|
// 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 we can't poll the device, skip
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
@ -182,15 +294,40 @@ public:
|
|||||||
|
|
||||||
class xinput_joystick_module : public wininput_module
|
class xinput_joystick_module : public wininput_module
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
xinput_interface* xinput_api;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
xinput_joystick_module()
|
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:
|
protected:
|
||||||
virtual void input_init(running_machine &machine) override
|
virtual void input_init(running_machine &machine) override
|
||||||
{
|
{
|
||||||
|
// The Xinput API should have been obtained already
|
||||||
|
assert(xinput_api != nullptr);
|
||||||
|
|
||||||
xinput_joystick_device *devinfo;
|
xinput_joystick_device *devinfo;
|
||||||
|
|
||||||
// Loop through each gamepad to determine if they are connected
|
// Loop through each gamepad to determine if they are connected
|
||||||
@ -198,7 +335,7 @@ protected:
|
|||||||
{
|
{
|
||||||
XINPUT_STATE state = {0};
|
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
|
// allocate and link in a new device
|
||||||
devinfo = create_xinput_device(machine, i);
|
devinfo = create_xinput_device(machine, i);
|
||||||
@ -261,7 +398,7 @@ protected:
|
|||||||
xinput_joystick_device *devinfo;
|
xinput_joystick_device *devinfo;
|
||||||
|
|
||||||
XINPUT_CAPABILITIES caps = {0};
|
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
|
// If we can't get the capabilities skip this device
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user