mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
[HID] Added support for Xbox 360 Skylanders Portal
- This requires Zadig for installation of WinUSB driver for portal
This commit is contained in:
parent
7667958556
commit
7298536d46
|
|
@ -265,7 +265,6 @@ workspace("xenia")
|
||||||
include("third_party/fmt.lua")
|
include("third_party/fmt.lua")
|
||||||
include("third_party/glslang-spirv.lua")
|
include("third_party/glslang-spirv.lua")
|
||||||
include("third_party/imgui.lua")
|
include("third_party/imgui.lua")
|
||||||
include("third_party/libusb.lua")
|
|
||||||
include("third_party/mspack.lua")
|
include("third_party/mspack.lua")
|
||||||
include("third_party/snappy.lua")
|
include("third_party/snappy.lua")
|
||||||
include("third_party/xxhash.lua")
|
include("third_party/xxhash.lua")
|
||||||
|
|
@ -274,6 +273,10 @@ workspace("xenia")
|
||||||
include("third_party/zlib.lua")
|
include("third_party/zlib.lua")
|
||||||
include("third_party/pugixml.lua")
|
include("third_party/pugixml.lua")
|
||||||
|
|
||||||
|
if os.istarget("windows") then
|
||||||
|
include("third_party/libusb.lua")
|
||||||
|
end
|
||||||
|
|
||||||
if not os.istarget("android") then
|
if not os.istarget("android") then
|
||||||
-- SDL2 requires sdl2-config, and as of November 2020 isn't high-quality on
|
-- SDL2 requires sdl2-config, and as of November 2020 isn't high-quality on
|
||||||
-- Android yet, most importantly in game controllers - the keycode and axis
|
-- Android yet, most importantly in game controllers - the keycode and axis
|
||||||
|
|
@ -308,6 +311,7 @@ workspace("xenia")
|
||||||
include("src/xenia/gpu/vulkan")
|
include("src/xenia/gpu/vulkan")
|
||||||
include("src/xenia/hid")
|
include("src/xenia/hid")
|
||||||
include("src/xenia/hid/nop")
|
include("src/xenia/hid/nop")
|
||||||
|
include("src/xenia/hid/skylander")
|
||||||
include("src/xenia/kernel")
|
include("src/xenia/kernel")
|
||||||
include("src/xenia/patcher")
|
include("src/xenia/patcher")
|
||||||
include("src/xenia/ui")
|
include("src/xenia/ui")
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ project("xenia-cpu-ppc-tests")
|
||||||
"xenia-base",
|
"xenia-base",
|
||||||
"xenia-kernel",
|
"xenia-kernel",
|
||||||
"xenia-patcher",
|
"xenia-patcher",
|
||||||
|
"xenia-hid-skylander",
|
||||||
})
|
})
|
||||||
files({
|
files({
|
||||||
"ppc_testing_main.cc",
|
"ppc_testing_main.cc",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ test_suite("xenia-cpu-tests", project_root, ".", {
|
||||||
"xenia-core",
|
"xenia-core",
|
||||||
"xenia-cpu",
|
"xenia-cpu",
|
||||||
"xenia-gpu",
|
"xenia-gpu",
|
||||||
|
"xenia-hid-skylander",
|
||||||
|
|
||||||
-- TODO(benvanik): cut these dependencies?
|
-- TODO(benvanik): cut these dependencies?
|
||||||
"xenia-kernel",
|
"xenia-kernel",
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ project("xenia-gpu-d3d12-trace-viewer")
|
||||||
"xenia-gpu-d3d12",
|
"xenia-gpu-d3d12",
|
||||||
"xenia-hid",
|
"xenia-hid",
|
||||||
"xenia-hid-nop",
|
"xenia-hid-nop",
|
||||||
|
"xenia-hid-skylander",
|
||||||
"xenia-kernel",
|
"xenia-kernel",
|
||||||
"xenia-patcher",
|
"xenia-patcher",
|
||||||
"xenia-ui",
|
"xenia-ui",
|
||||||
|
|
@ -86,6 +87,7 @@ project("xenia-gpu-d3d12-trace-dump")
|
||||||
"xenia-gpu-d3d12",
|
"xenia-gpu-d3d12",
|
||||||
"xenia-hid",
|
"xenia-hid",
|
||||||
"xenia-hid-nop",
|
"xenia-hid-nop",
|
||||||
|
"xenia-hid-skylander",
|
||||||
"xenia-kernel",
|
"xenia-kernel",
|
||||||
"xenia-ui",
|
"xenia-ui",
|
||||||
"xenia-ui-d3d12",
|
"xenia-ui-d3d12",
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ project("xenia-gpu-vulkan-trace-viewer")
|
||||||
"xenia-gpu-vulkan",
|
"xenia-gpu-vulkan",
|
||||||
"xenia-hid",
|
"xenia-hid",
|
||||||
"xenia-hid-nop",
|
"xenia-hid-nop",
|
||||||
|
"xenia-hid-skylander",
|
||||||
"xenia-kernel",
|
"xenia-kernel",
|
||||||
"xenia-patcher",
|
"xenia-patcher",
|
||||||
"xenia-ui",
|
"xenia-ui",
|
||||||
|
|
@ -102,6 +103,7 @@ project("xenia-gpu-vulkan-trace-dump")
|
||||||
"xenia-gpu-vulkan",
|
"xenia-gpu-vulkan",
|
||||||
"xenia-hid",
|
"xenia-hid",
|
||||||
"xenia-hid-nop",
|
"xenia-hid-nop",
|
||||||
|
"xenia-hid-skylander",
|
||||||
"xenia-kernel",
|
"xenia-kernel",
|
||||||
"xenia-ui",
|
"xenia-ui",
|
||||||
"xenia-ui-vulkan",
|
"xenia-ui-vulkan",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@
|
||||||
#include "xenia/hid/input_driver.h"
|
#include "xenia/hid/input_driver.h"
|
||||||
#include "xenia/kernel/util/shim_utils.h"
|
#include "xenia/kernel/util/shim_utils.h"
|
||||||
|
|
||||||
|
#include "xenia/hid/skylander/skylander_emulated.h"
|
||||||
|
#ifdef XE_PLATFORM_WIN32
|
||||||
|
#include "xenia/hid/skylander/skylander_hardware.h"
|
||||||
|
#endif // XE_PLATFORM_WIN32
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace hid {
|
namespace hid {
|
||||||
|
|
||||||
|
|
@ -28,7 +33,13 @@ DEFINE_double(
|
||||||
right_stick_deadzone_percentage, 0.0,
|
right_stick_deadzone_percentage, 0.0,
|
||||||
"Defines deadzone level for right stick. Allowed range [0.0-1.0].", "HID");
|
"Defines deadzone level for right stick. Allowed range [0.0-1.0].", "HID");
|
||||||
|
|
||||||
InputSystem::InputSystem(xe::ui::Window* window) : window_(window) {}
|
InputSystem::InputSystem(xe::ui::Window* window) : window_(window) {
|
||||||
|
skylander_portal_ = std::make_unique<SkylanderPortalEmulated>();
|
||||||
|
|
||||||
|
#ifdef XE_PLATFORM_WIN32
|
||||||
|
skylander_portal_ = std::make_unique<SkylanderPortalLibusb>();
|
||||||
|
#endif // XE_PLATFORM_WIN32
|
||||||
|
}
|
||||||
|
|
||||||
InputSystem::~InputSystem() = default;
|
InputSystem::~InputSystem() = default;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
#include "xenia/base/mutex.h"
|
#include "xenia/base/mutex.h"
|
||||||
#include "xenia/hid/input.h"
|
#include "xenia/hid/input.h"
|
||||||
#include "xenia/hid/input_driver.h"
|
#include "xenia/hid/input_driver.h"
|
||||||
|
#include "xenia/hid/skylander/skylander_portal.h"
|
||||||
#include "xenia/xbox.h"
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|
@ -55,6 +56,8 @@ class InputSystem {
|
||||||
|
|
||||||
uint32_t GetLastUsedSlot() const { return last_used_slot; }
|
uint32_t GetLastUsedSlot() const { return last_used_slot; }
|
||||||
|
|
||||||
|
SkylanderPortal* GetSkylanderPortal() { return skylander_portal_.get(); }
|
||||||
|
|
||||||
std::unique_lock<xe_unlikely_mutex> lock();
|
std::unique_lock<xe_unlikely_mutex> lock();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -74,6 +77,8 @@ class InputSystem {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<InputDriver>> drivers_;
|
std::vector<std::unique_ptr<InputDriver>> drivers_;
|
||||||
|
|
||||||
|
std::unique_ptr<SkylanderPortal> skylander_portal_;
|
||||||
|
|
||||||
std::bitset<XUserMaxUserCount> connected_slots = {};
|
std::bitset<XUserMaxUserCount> connected_slots = {};
|
||||||
std::array<std::pair<joystick_value, joystick_value>, XUserMaxUserCount>
|
std::array<std::pair<joystick_value, joystick_value>, XUserMaxUserCount>
|
||||||
controllers_max_joystick_value = {};
|
controllers_max_joystick_value = {};
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ project("xenia-hid")
|
||||||
language("C++")
|
language("C++")
|
||||||
links({
|
links({
|
||||||
"xenia-base",
|
"xenia-base",
|
||||||
|
"xenia-hid-skylander",
|
||||||
})
|
})
|
||||||
defines({
|
defines({
|
||||||
})
|
})
|
||||||
|
|
|
||||||
23
src/xenia/hid/skylander/premake5.lua
Normal file
23
src/xenia/hid/skylander/premake5.lua
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
project_root = "../../../.."
|
||||||
|
include(project_root.."/tools/build")
|
||||||
|
|
||||||
|
group("src")
|
||||||
|
project("xenia-hid-skylander")
|
||||||
|
uuid("ddc114da-a279-4868-8b20-53108599bd78")
|
||||||
|
kind("StaticLib")
|
||||||
|
language("C++")
|
||||||
|
files({
|
||||||
|
"skylander_portal.h",
|
||||||
|
"skylander_portal.cc",
|
||||||
|
"skylander_emulated.h",
|
||||||
|
"skylander_emulated.cc"
|
||||||
|
})
|
||||||
|
|
||||||
|
filter({"platforms:Windows"})
|
||||||
|
links({
|
||||||
|
"libusb",
|
||||||
|
})
|
||||||
|
files({
|
||||||
|
"skylander_hardware.h",
|
||||||
|
"skylander_hardware.cc"
|
||||||
|
})
|
||||||
32
src/xenia/hid/skylander/skylander_emulated.cc
Normal file
32
src/xenia/hid/skylander/skylander_emulated.cc
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xenia/hid/skylander/skylander_emulated.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace hid {
|
||||||
|
|
||||||
|
SkylanderPortalEmulated::SkylanderPortalEmulated() : SkylanderPortal() {}
|
||||||
|
|
||||||
|
SkylanderPortalEmulated::~SkylanderPortalEmulated() {}
|
||||||
|
|
||||||
|
bool SkylanderPortalEmulated::init_device() { return false; }
|
||||||
|
|
||||||
|
void SkylanderPortalEmulated::destroy_device() {}
|
||||||
|
|
||||||
|
X_STATUS SkylanderPortalEmulated::read(std::vector<uint8_t>& data) {
|
||||||
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
X_STATUS SkylanderPortalEmulated::write(std::vector<uint8_t>& data) {
|
||||||
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace hid
|
||||||
|
} // namespace xe
|
||||||
34
src/xenia/hid/skylander/skylander_emulated.h
Normal file
34
src/xenia/hid/skylander/skylander_emulated.h
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_EMULATED_H_
|
||||||
|
#define XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_EMULATED_H_
|
||||||
|
|
||||||
|
#include "xenia/hid/skylander/skylander_portal.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace hid {
|
||||||
|
|
||||||
|
class SkylanderPortalEmulated final : public SkylanderPortal {
|
||||||
|
public:
|
||||||
|
SkylanderPortalEmulated();
|
||||||
|
~SkylanderPortalEmulated() override;
|
||||||
|
|
||||||
|
X_STATUS read(std::vector<uint8_t>& data) override;
|
||||||
|
X_STATUS write(std::vector<uint8_t>& data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool init_device() override;
|
||||||
|
void destroy_device() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace hid
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif
|
||||||
121
src/xenia/hid/skylander/skylander_hardware.cc
Normal file
121
src/xenia/hid/skylander/skylander_hardware.cc
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xenia/hid/skylander/skylander_hardware.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace hid {
|
||||||
|
|
||||||
|
SkylanderPortalLibusb::SkylanderPortalLibusb() : SkylanderPortal() {
|
||||||
|
libusb_init(&context_);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkylanderPortalLibusb::~SkylanderPortalLibusb() {
|
||||||
|
if (handle_) {
|
||||||
|
destroy_device();
|
||||||
|
}
|
||||||
|
|
||||||
|
libusb_exit(context_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkylanderPortalLibusb::init_device() {
|
||||||
|
if (!context_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
libusb_device** devs;
|
||||||
|
ssize_t cnt = libusb_get_device_list(context_, &devs);
|
||||||
|
if (cnt < 0) {
|
||||||
|
// No device available... It might appear later.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool device_found = false;
|
||||||
|
for (ssize_t i = 0; i < cnt; ++i) {
|
||||||
|
libusb_device* dev = devs[i];
|
||||||
|
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
if (libusb_get_device_descriptor(dev, &desc) == 0) {
|
||||||
|
// Check if this device matches the target Vendor ID and Product ID
|
||||||
|
if (desc.idVendor == portal_vendor_product_id.first &&
|
||||||
|
desc.idProduct == portal_vendor_product_id.second) {
|
||||||
|
libusb_device_handle* handle;
|
||||||
|
if (libusb_open(dev, &handle) == 0) {
|
||||||
|
libusb_claim_interface(handle, 0);
|
||||||
|
handle_ = reinterpret_cast<uintptr_t*>(handle);
|
||||||
|
device_found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
libusb_free_device_list(devs, 0);
|
||||||
|
|
||||||
|
return device_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkylanderPortalLibusb::destroy_device() {
|
||||||
|
libusb_release_interface(reinterpret_cast<libusb_device_handle*>(handle_), 0);
|
||||||
|
libusb_close(reinterpret_cast<libusb_device_handle*>(handle_));
|
||||||
|
handle_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
X_STATUS SkylanderPortalLibusb::read(std::vector<uint8_t>& data) {
|
||||||
|
if (!is_initialized()) {
|
||||||
|
if (!init_device()) {
|
||||||
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.size() > skylander_buffer_size) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int result = libusb_interrupt_transfer(
|
||||||
|
reinterpret_cast<libusb_device_handle*>(handle_), read_endpoint,
|
||||||
|
data.data(), static_cast<int>(data.size()), nullptr, timeout);
|
||||||
|
|
||||||
|
if (result == LIBUSB_ERROR_NO_DEVICE) {
|
||||||
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
destroy_device();
|
||||||
|
}
|
||||||
|
|
||||||
|
return X_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
X_STATUS SkylanderPortalLibusb::write(std::vector<uint8_t>& data) {
|
||||||
|
if (!is_initialized()) {
|
||||||
|
if (!init_device()) {
|
||||||
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.size() > skylander_buffer_size) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int result = libusb_interrupt_transfer(
|
||||||
|
reinterpret_cast<libusb_device_handle*>(handle_), write_endpoint,
|
||||||
|
data.data(), static_cast<int>(data.size()), nullptr, timeout);
|
||||||
|
|
||||||
|
if (result == LIBUSB_ERROR_NO_DEVICE) {
|
||||||
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
destroy_device();
|
||||||
|
}
|
||||||
|
|
||||||
|
return X_ERROR_SUCCESS;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace hid
|
||||||
|
} // namespace xe
|
||||||
47
src/xenia/hid/skylander/skylander_hardware.h
Normal file
47
src/xenia/hid/skylander/skylander_hardware.h
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_LIBUSB_H_
|
||||||
|
#define XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_LIBUSB_H_
|
||||||
|
|
||||||
|
// Include order is important here. Including skylander_portal.h after libusb
|
||||||
|
// will cause conflicts.
|
||||||
|
#include "xenia/hid/skylander/skylander_portal.h"
|
||||||
|
|
||||||
|
#include "third_party/libusb/libusb/libusb.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace hid {
|
||||||
|
|
||||||
|
class SkylanderPortalLibusb final : public SkylanderPortal {
|
||||||
|
public:
|
||||||
|
SkylanderPortalLibusb();
|
||||||
|
~SkylanderPortalLibusb() override;
|
||||||
|
|
||||||
|
X_STATUS read(std::vector<uint8_t>& data) override;
|
||||||
|
X_STATUS write(std::vector<uint8_t>& data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool init_device() override;
|
||||||
|
void destroy_device() override;
|
||||||
|
|
||||||
|
bool is_initialized() const { return handle_ != nullptr; }
|
||||||
|
|
||||||
|
const uint8_t read_endpoint = 0x81;
|
||||||
|
const uint8_t write_endpoint = 0x02;
|
||||||
|
const uint16_t timeout = 300;
|
||||||
|
|
||||||
|
libusb_context* context_ = nullptr;
|
||||||
|
uintptr_t* handle_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace hid
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif
|
||||||
19
src/xenia/hid/skylander/skylander_portal.cc
Normal file
19
src/xenia/hid/skylander/skylander_portal.cc
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xenia/hid/skylander/skylander_portal.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace hid {
|
||||||
|
|
||||||
|
SkylanderPortal::SkylanderPortal() {}
|
||||||
|
SkylanderPortal::~SkylanderPortal() {}
|
||||||
|
|
||||||
|
} // namespace hid
|
||||||
|
} // namespace xe
|
||||||
40
src/xenia/hid/skylander/skylander_portal.h
Normal file
40
src/xenia/hid/skylander/skylander_portal.h
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_H_
|
||||||
|
#define XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace hid {
|
||||||
|
|
||||||
|
constexpr std::pair<uint16_t, uint16_t> portal_vendor_product_id = {0x1430,
|
||||||
|
0x1F17};
|
||||||
|
constexpr uint8_t skylander_buffer_size = 0x20;
|
||||||
|
|
||||||
|
class SkylanderPortal {
|
||||||
|
public:
|
||||||
|
SkylanderPortal();
|
||||||
|
virtual ~SkylanderPortal();
|
||||||
|
|
||||||
|
virtual X_STATUS read(std::vector<uint8_t>& data) = 0;
|
||||||
|
virtual X_STATUS write(std::vector<uint8_t>& data) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool init_device() = 0;
|
||||||
|
virtual void destroy_device() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace hid
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -227,6 +227,44 @@ X_HRESULT_result_t XamUserGetDeviceContext_entry(
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamUserGetDeviceContext, kInput, kStub);
|
DECLARE_XAM_EXPORT1(XamUserGetDeviceContext, kInput, kStub);
|
||||||
|
|
||||||
|
X_HRESULT_result_t XamInputNonControllerGetRaw_entry(
|
||||||
|
lpdword_t state_ptr, lpdword_t buffer_length_ptr, lpdword_t buffer_ptr) {
|
||||||
|
if (!state_ptr || !buffer_length_ptr || !buffer_ptr) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t data_size = *buffer_length_ptr;
|
||||||
|
|
||||||
|
if (data_size == 0 || data_size > 0x20) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input_system = kernel_state()->emulator()->input_system();
|
||||||
|
|
||||||
|
std::vector<uint8_t> data(data_size, 0);
|
||||||
|
const auto result = input_system->GetSkylanderPortal()->read(data);
|
||||||
|
*state_ptr = 1;
|
||||||
|
memcpy(buffer_ptr, data.data(), data.size());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
DECLARE_XAM_EXPORT1(XamInputNonControllerGetRaw, kInput, kStub);
|
||||||
|
|
||||||
|
X_HRESULT_result_t XamInputNonControllerSetRaw_entry(dword_t buffer_length,
|
||||||
|
lpdword_t buffer_ptr) {
|
||||||
|
if (!buffer_ptr || !buffer_length || buffer_length > 0x20) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input_system = kernel_state()->emulator()->input_system();
|
||||||
|
|
||||||
|
std::vector<uint8_t> data(buffer_length, 0);
|
||||||
|
memcpy(data.data(), buffer_ptr, buffer_length);
|
||||||
|
|
||||||
|
return input_system->GetSkylanderPortal()->write(data);
|
||||||
|
}
|
||||||
|
DECLARE_XAM_EXPORT1(XamInputNonControllerSetRaw, kInput, kStub);
|
||||||
|
|
||||||
} // namespace xam
|
} // namespace xam
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue