Files
Xenia-Canary/src/xenia/kernel/xam/xam_input.cc

208 lines
7.3 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/base/logging.h"
#include "xenia/emulator.h"
#include "xenia/hid/input.h"
#include "xenia/hid/input_system.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xam/xam_private.h"
#include "xenia/xbox.h"
namespace xe {
namespace kernel {
namespace xam {
using xe::hid::X_INPUT_CAPABILITIES;
using xe::hid::X_INPUT_KEYSTROKE;
using xe::hid::X_INPUT_STATE;
using xe::hid::X_INPUT_VIBRATION;
constexpr uint32_t XINPUT_FLAG_GAMEPAD = 0x01;
constexpr uint32_t XINPUT_FLAG_ANY_USER = 1 << 30;
void XamResetInactivity() {
// Do we need to do anything?
}
DECLARE_XAM_EXPORT(XamResetInactivity, ExportTag::kInput | ExportTag::kStub);
dword_result_t XamEnableInactivityProcessing(dword_t unk, dword_t enable) {
return X_ERROR_SUCCESS;
}
DECLARE_XAM_EXPORT(XamEnableInactivityProcessing,
ExportTag::kInput | ExportTag::kStub);
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetcapabilities(v=vs.85).aspx
dword_result_t XamInputGetCapabilities(dword_t user_index, dword_t flags,
pointer_t<X_INPUT_CAPABILITIES> caps) {
if (!caps) {
return X_ERROR_BAD_ARGUMENTS;
}
if ((flags & 0xFF) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
// Ignore any query for other types of devices.
return X_ERROR_DEVICE_NOT_CONNECTED;
}
uint32_t actual_user_index = user_index;
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
// Always pin user to 0.
actual_user_index = 0;
}
auto input_system = kernel_state()->emulator()->input_system();
return input_system->GetCapabilities(actual_user_index, flags, caps);
}
DECLARE_XAM_EXPORT(XamInputGetCapabilities,
ExportTag::kInput | ExportTag::kSketchy);
dword_result_t XamInputGetCapabilitiesEx(dword_t unk, dword_t user_index,
dword_t flags,
pointer_t<X_INPUT_CAPABILITIES> caps) {
if (!caps) {
return X_ERROR_BAD_ARGUMENTS;
}
if ((flags & 0xFF) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
// Ignore any query for other types of devices.
return X_ERROR_DEVICE_NOT_CONNECTED;
}
uint32_t actual_user_index = user_index;
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
// Always pin user to 0.
actual_user_index = 0;
}
auto input_system = kernel_state()->emulator()->input_system();
return input_system->GetCapabilities(actual_user_index, flags, caps);
}
DECLARE_XAM_EXPORT(XamInputGetCapabilitiesEx,
ExportTag::kInput | ExportTag::kSketchy);
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetstate(v=vs.85).aspx
dword_result_t XamInputGetState(dword_t user_index, dword_t flags,
pointer_t<X_INPUT_STATE> input_state) {
// Games call this with a NULL state ptr, probably as a query.
if ((flags & 0xFF) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
// Ignore any query for other types of devices.
return X_ERROR_DEVICE_NOT_CONNECTED;
}
uint32_t actual_user_index = user_index;
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
// Always pin user to 0.
actual_user_index = 0;
}
auto input_system = kernel_state()->emulator()->input_system();
return input_system->GetState(user_index, input_state);
}
DECLARE_XAM_EXPORT(XamInputGetState,
ExportTag::kInput | ExportTag::kImplemented);
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputsetstate(v=vs.85).aspx
dword_result_t XamInputSetState(dword_t user_index, dword_t unk,
pointer_t<X_INPUT_VIBRATION> vibration) {
if (!vibration) {
return X_ERROR_BAD_ARGUMENTS;
}
uint32_t actual_user_index = user_index;
if ((user_index & 0xFF) == 0xFF) {
// Always pin user to 0.
actual_user_index = 0;
}
auto input_system = kernel_state()->emulator()->input_system();
return input_system->SetState(user_index, vibration);
}
DECLARE_XAM_EXPORT(XamInputSetState,
ExportTag::kInput | ExportTag::kImplemented);
// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetkeystroke(v=vs.85).aspx
dword_result_t XamInputGetKeystroke(dword_t user_index, dword_t flags,
pointer_t<X_INPUT_KEYSTROKE> keystroke) {
// http://ffplay360.googlecode.com/svn/Test/Common/AtgXime.cpp
// user index = index or XUSER_INDEX_ANY
// flags = XINPUT_FLAG_GAMEPAD (| _ANYUSER | _ANYDEVICE)
if (!keystroke) {
return X_ERROR_BAD_ARGUMENTS;
}
if ((flags & 0xFF) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
// Ignore any query for other types of devices.
return X_ERROR_DEVICE_NOT_CONNECTED;
}
uint32_t actual_user_index = user_index;
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
// Always pin user to 0.
actual_user_index = 0;
}
auto input_system = kernel_state()->emulator()->input_system();
return input_system->GetKeystroke(user_index, flags, keystroke);
}
DECLARE_XAM_EXPORT(XamInputGetKeystroke,
ExportTag::kInput | ExportTag::kImplemented);
// Same as non-ex, just takes a pointer to user index.
dword_result_t XamInputGetKeystrokeEx(lpdword_t user_index_ptr, dword_t flags,
pointer_t<X_INPUT_KEYSTROKE> keystroke) {
if (!keystroke) {
return X_ERROR_BAD_ARGUMENTS;
}
if ((flags & 0xFF) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
// Ignore any query for other types of devices.
return X_ERROR_DEVICE_NOT_CONNECTED;
}
uint32_t user_index = *user_index_ptr;
if ((user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
// Always pin user to 0.
user_index = 0;
}
auto input_system = kernel_state()->emulator()->input_system();
auto result = input_system->GetKeystroke(user_index, flags, keystroke);
if (XSUCCEEDED(result)) {
*user_index_ptr = keystroke->user_index;
}
return result;
}
DECLARE_XAM_EXPORT(XamInputGetKeystrokeEx,
ExportTag::kInput | ExportTag::kImplemented);
X_HRESULT_result_t XamUserGetDeviceContext(dword_t user_index, dword_t unk,
lpdword_t out_ptr) {
// Games check the result - usually with some masking.
// If this function fails they assume zero, so let's fail AND
// set zero just to be safe.
*out_ptr = 0;
if (!user_index || (user_index & 0xFF) == 0xFF) {
return X_E_SUCCESS;
} else {
return X_E_DEVICE_NOT_CONNECTED;
}
}
DECLARE_XAM_EXPORT(XamUserGetDeviceContext,
ExportTag::kInput | ExportTag::kStub);
void RegisterInputExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state) {}
} // namespace xam
} // namespace kernel
} // namespace xe