summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgibbed <rick@gibbed.us>2018-11-22 10:46:48 -0600
committergibbed <rick@gibbed.us>2018-11-22 10:46:48 -0600
commit086d7e9da7309e2c987fac16deb7993ad6e1e4a6 (patch)
tree8cfa1fb4315aa78f6294e7357652cf7cefc33151
parent86d2c9ae1e82424ce2840a56e359a6b283c49778 (diff)
[Input] Dynamically link to XInput.
-rw-r--r--src/xenia/app/xenia_main.cc13
-rw-r--r--src/xenia/hid/xinput/xinput_input_driver.cc74
-rw-r--r--src/xenia/hid/xinput/xinput_input_driver.h6
-rw-r--r--src/xenia/xbox.h2
4 files changed, 76 insertions, 19 deletions
diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc
index ee474485b..827584af0 100644
--- a/src/xenia/app/xenia_main.cc
+++ b/src/xenia/app/xenia_main.cc
@@ -119,11 +119,18 @@ std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
drivers.emplace_back(std::move(winkey_driver));
}
#endif // XE_PLATFORM_WIN32
- if (drivers.empty()) {
- // Fallback to nop if none created.
- drivers.emplace_back(xe::hid::nop::Create(window));
+ }
+ for (auto it = drivers.begin(); it != drivers.end();) {
+ if (XFAILED((*it)->Setup())) {
+ it = drivers.erase(it);
+ } else {
+ ++it;
}
}
+ if (drivers.empty()) {
+ // Fallback to nop if none created.
+ drivers.emplace_back(xe::hid::nop::Create(window));
+ }
return drivers;
}
diff --git a/src/xenia/hid/xinput/xinput_input_driver.cc b/src/xenia/hid/xinput/xinput_input_driver.cc
index 937b66801..9e6d2f90c 100644
--- a/src/xenia/hid/xinput/xinput_input_driver.cc
+++ b/src/xenia/hid/xinput/xinput_input_driver.cc
@@ -21,26 +21,64 @@ namespace hid {
namespace xinput {
XInputInputDriver::XInputInputDriver(xe::ui::Window* window)
- : InputDriver(window) {
-#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8 && _WIN32_WINNT < _WIN32_WINNT_WIN10)
- // TODO(gibbed): Is this necessary?
- XInputEnable(TRUE);
-#endif
-}
+ : InputDriver(window),
+ module_(nullptr),
+ XInputGetCapabilities_(nullptr),
+ XInputGetState_(nullptr),
+ XInputGetKeystroke_(nullptr),
+ XInputSetState_(nullptr),
+ XInputEnable_(nullptr) {}
XInputInputDriver::~XInputInputDriver() {
-#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8 && _WIN32_WINNT < _WIN32_WINNT_WIN10)
- // TODO(gibbed): Is this necessary?
- XInputEnable(FALSE);
-#endif
+ if (module_) {
+ FreeLibrary((HMODULE)module_);
+ module_ = nullptr;
+ XInputGetCapabilities_ = nullptr;
+ XInputGetState_ = nullptr;
+ XInputGetKeystroke_ = nullptr;
+ XInputSetState_ = nullptr;
+ XInputEnable_ = nullptr;
+ }
}
-X_STATUS XInputInputDriver::Setup() { return X_STATUS_SUCCESS; }
+X_STATUS XInputInputDriver::Setup() {
+ HMODULE module = LoadLibraryW(L"xinput1_4.dll");
+ if (!module) {
+ module = LoadLibraryW(L"xinput1_3.dll");
+ }
+ if (!module) {
+ return X_STATUS_DLL_NOT_FOUND;
+ }
+
+ // Required.
+ auto xigc = GetProcAddress(module, "XInputGetCapabilities");
+ auto xigs = GetProcAddress(module, "XInputGetState");
+ auto xigk = GetProcAddress(module, "XInputGetKeystroke");
+ auto xiss = GetProcAddress(module, "XInputSetState");
+
+ // Not required.
+ auto xie = GetProcAddress(module, "XInputEnable");
+
+ // Only fail when we don't have the bare essentials;
+ if (!xigc || !xigs || !xigk || !xiss) {
+ FreeLibrary(module);
+ return X_STATUS_PROCEDURE_NOT_FOUND;
+ }
+
+ module_ = module;
+ XInputGetCapabilities_ = xigc;
+ XInputGetState_ = xigs;
+ XInputGetKeystroke_ = xigk;
+ XInputSetState_ = xiss;
+ XInputEnable_ = xie;
+ return X_STATUS_SUCCESS;
+}
X_RESULT XInputInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
X_INPUT_CAPABILITIES* out_caps) {
XINPUT_CAPABILITIES native_caps;
- DWORD result = XInputGetCapabilities(user_index, flags, &native_caps);
+ auto xigc = (decltype(&XInputGetCapabilities))XInputGetCapabilities_;
+ DWORD result = xigc(user_index, flags, &native_caps);
if (result) {
return result;
}
@@ -65,7 +103,8 @@ X_RESULT XInputInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
X_RESULT XInputInputDriver::GetState(uint32_t user_index,
X_INPUT_STATE* out_state) {
XINPUT_STATE native_state;
- DWORD result = XInputGetState(user_index, &native_state);
+ auto xigs = (decltype(&XInputGetState))XInputGetState_;
+ DWORD result = xigs(user_index, &native_state);
if (result) {
return result;
}
@@ -87,7 +126,8 @@ X_RESULT XInputInputDriver::SetState(uint32_t user_index,
XINPUT_VIBRATION native_vibration;
native_vibration.wLeftMotorSpeed = vibration->left_motor_speed;
native_vibration.wRightMotorSpeed = vibration->right_motor_speed;
- DWORD result = XInputSetState(user_index, &native_vibration);
+ auto xiss = (decltype(&XInputSetState))XInputSetState_;
+ DWORD result = xiss(user_index, &native_vibration);
return result;
}
@@ -104,13 +144,15 @@ X_RESULT XInputInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
// So we first check if the device is connected via XInputGetCapabilities, so
// we are not passing back an uninitialized X_INPUT_KEYSTROKE structure:
XINPUT_CAPABILITIES caps;
- result = XInputGetCapabilities(user_index, 0, &caps);
+ auto xigc = (decltype(&XInputGetCapabilities))XInputGetCapabilities_;
+ result = xigc(user_index, 0, &caps);
if (result) {
return result;
}
XINPUT_KEYSTROKE native_keystroke;
- result = XInputGetKeystroke(user_index, 0, &native_keystroke);
+ auto xigk = (decltype(&XInputGetKeystroke))XInputGetKeystroke_;
+ result = xigk(user_index, 0, &native_keystroke);
if (result) {
return result;
}
diff --git a/src/xenia/hid/xinput/xinput_input_driver.h b/src/xenia/hid/xinput/xinput_input_driver.h
index fbf75c422..dcde26197 100644
--- a/src/xenia/hid/xinput/xinput_input_driver.h
+++ b/src/xenia/hid/xinput/xinput_input_driver.h
@@ -31,6 +31,12 @@ class XInputInputDriver : public InputDriver {
X_INPUT_KEYSTROKE* out_keystroke) override;
protected:
+ void* module_;
+ void* XInputGetCapabilities_;
+ void* XInputGetState_;
+ void* XInputGetKeystroke_;
+ void* XInputSetState_;
+ void* XInputEnable_;
};
} // namespace xinput
diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h
index a98edd24a..4884c260e 100644
--- a/src/xenia/xbox.h
+++ b/src/xenia/xbox.h
@@ -60,6 +60,7 @@ typedef uint32_t X_STATUS;
#define X_STATUS_OBJECT_NAME_COLLISION ((X_STATUS)0xC0000035L)
#define X_STATUS_INVALID_PAGE_PROTECTION ((X_STATUS)0xC0000045L)
#define X_STATUS_MUTANT_NOT_OWNED ((X_STATUS)0xC0000046L)
+#define X_STATUS_PROCEDURE_NOT_FOUND ((X_STATUS)0xC000007AL)
#define X_STATUS_INSUFFICIENT_RESOURCES ((X_STATUS)0xC000009AL)
#define X_STATUS_MEMORY_NOT_ALLOCATED ((X_STATUS)0xC00000A0L)
#define X_STATUS_NOT_SUPPORTED ((X_STATUS)0xC00000BBL)
@@ -67,6 +68,7 @@ typedef uint32_t X_STATUS;
#define X_STATUS_INVALID_PARAMETER_2 ((X_STATUS)0xC00000F0L)
#define X_STATUS_INVALID_PARAMETER_3 ((X_STATUS)0xC00000F1L)
#define X_STATUS_DLL_NOT_FOUND ((X_STATUS)0xC0000135L)
+#define X_STATUS_ENTRYPOINT_NOT_FOUND ((X_STATUS)0xC0000139L)
#define X_STATUS_MAPPED_ALIGNMENT ((X_STATUS)0xC0000220L)
#define X_STATUS_NOT_FOUND ((X_STATUS)0xC0000225L)
#define X_STATUS_DRIVER_ORDINAL_NOT_FOUND ((X_STATUS)0xC0000262L)