diff --git a/hw/amdgpu/bridge/include/amdgpu/bridge/bridge.hpp b/hw/amdgpu/bridge/include/amdgpu/bridge/bridge.hpp index 8e8642981..10863b43b 100644 --- a/hw/amdgpu/bridge/include/amdgpu/bridge/bridge.hpp +++ b/hw/amdgpu/bridge/include/amdgpu/bridge/bridge.hpp @@ -8,6 +8,38 @@ #include namespace amdgpu::bridge { +struct PadState { + std::uint64_t timestamp; + std::uint32_t unk; + std::uint32_t buttons; + std::uint8_t leftStickX; + std::uint8_t leftStickY; + std::uint8_t rightStickX; + std::uint8_t rightStickY; + std::uint8_t l2; + std::uint8_t r2; +}; + +enum { + kPadBtnL3 = 1 << 1, + kPadBtnR3 = 1 << 2, + kPadBtnOptions = 1 << 3, + kPadBtnUp = 1 << 4, + kPadBtnRight = 1 << 5, + kPadBtnDown = 1 << 6, + kPadBtnLeft = 1 << 7, + kPadBtnL2 = 1 << 8, + kPadBtnR2 = 1 << 9, + kPadBtnL1 = 1 << 10, + kPadBtnR1 = 1 << 11, + kPadBtnTriangle = 1 << 12, + kPadBtnCircle = 1 << 13, + kPadBtnCross = 1 << 14, + kPadBtnSquare = 1 << 15, + kPadBtnTouchPad = 1 << 20, + kPadBtnIntercepted = 1 << 31, +}; + enum class CommandId : std::uint32_t { Nop, ProtectMemory, @@ -59,6 +91,7 @@ struct BridgeHeader { std::uint64_t vmAddress; std::uint64_t vmSize; char vmName[32]; + PadState kbPadState; volatile std::uint32_t flipBuffer; volatile std::uint64_t flipArg; volatile std::uint64_t flipCount; diff --git a/rpcsx-gpu/main.cpp b/rpcsx-gpu/main.cpp index 0c97a8e11..cc740e514 100644 --- a/rpcsx-gpu/main.cpp +++ b/rpcsx-gpu/main.cpp @@ -778,6 +778,88 @@ int main(int argc, const char *argv[]) { std::size_t pulledCount = bridgePuller.pullCommands(commandsBuffer, std::size(commandsBuffer)); + bridge->kbPadState.leftStickX = 0x80; + bridge->kbPadState.leftStickY = 0x80; + bridge->kbPadState.rightStickX = 0x80; + bridge->kbPadState.rightStickY = 0x80; + bridge->kbPadState.buttons = 0; + + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { + bridge->kbPadState.leftStickX = 0; + } else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { + bridge->kbPadState.leftStickX = 0xff; + } + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { + bridge->kbPadState.leftStickY = 0; + } else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { + bridge->kbPadState.leftStickY = 0xff; + } + + if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) { + bridge->kbPadState.rightStickX = 0; + } else if (glfwGetKey(window, GLFW_KEY_L) == GLFW_PRESS) { + bridge->kbPadState.rightStickX = 0xff; + } + if (glfwGetKey(window, GLFW_KEY_K) == GLFW_PRESS) { + bridge->kbPadState.rightStickY = 0; + } else if (glfwGetKey(window, GLFW_KEY_SEMICOLON) == GLFW_PRESS) { + bridge->kbPadState.rightStickY = 0xff; + } + + if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnUp; + } + if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnDown; + } + if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnLeft; + } + if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnRight; + } + if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnSquare; + } + if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnCross; + } + if (glfwGetKey(window, GLFW_KEY_C) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnCircle; + } + if (glfwGetKey(window, GLFW_KEY_V) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnTriangle; + } + + if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnL1; + } + if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnL2; + bridge->kbPadState.l2 = 0xff; + } + if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnL3; + } + + if (glfwGetKey(window, GLFW_KEY_I) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnR1; + } + if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnR2; + bridge->kbPadState.r2 = 0xff; + } + if (glfwGetKey(window, GLFW_KEY_APOSTROPHE) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnL3; + } + + if (glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS) { + bridge->kbPadState.buttons |= amdgpu::bridge::kPadBtnOptions; + } + + bridge->kbPadState.timestamp = + std::chrono::high_resolution_clock::now().time_since_epoch().count(); + if (pulledCount == 0) { // std::this_thread::sleep_for( // std::chrono::milliseconds(1)); // Just for testing, should be diff --git a/rpcsx-os/iodev/hid.cpp b/rpcsx-os/iodev/hid.cpp index aed152cd6..6c2ad0c31 100644 --- a/rpcsx-os/iodev/hid.cpp +++ b/rpcsx-os/iodev/hid.cpp @@ -1,8 +1,11 @@ +#include "amdgpu/bridge/bridge.hpp" +#include "bridge.hpp" #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" #include "orbis/file.hpp" #include "orbis/thread/Thread.hpp" #include "orbis/utils/Logs.hpp" +#include struct HidDevice : public IoDevice { orbis::ErrorCode open(orbis::Ref *file, const char *path, @@ -13,8 +16,6 @@ struct HidFile : public orbis::File {}; static orbis::ErrorCode hid_ioctl(orbis::File *file, std::uint64_t request, void *argp, orbis::Thread *thread) { - ORBIS_LOG_FATAL("Unhandled hid ioctl", request); - ORBIS_LOG_FATAL("hid ioctl", request); switch (request) { case 0x800c4802: @@ -26,16 +27,61 @@ static orbis::ErrorCode hid_ioctl(orbis::File *file, std::uint64_t request, struct ReadStateArgs { std::uint32_t hidId; std::uint32_t unk0; - void *unk1; + void *state; std::uint32_t unk2; - void *unk3; - void *unk4; + std::uint32_t *connected; + std::uint32_t *unk4; std::uint64_t unk5; }; + // struct PadState { + // std::uint64_t timestamp; + // std::uint32_t unk; + // std::uint32_t buttons; + // std::uint8_t leftStickX; + // std::uint8_t leftStickY; + // std::uint8_t rightStickX; + // std::uint8_t rightStickY; + // std::uint8_t l2; + // std::uint8_t r2; + // }; + + // enum { + // kPadBtnL3 = 1 << 1, + // kPadBtnR3 = 1 << 2, + // kPadBtnOptions = 1 << 3, + // kPadBtnUp = 1 << 4, + // kPadBtnRight = 1 << 5, + // kPadBtnDown = 1 << 6, + // kPadBtnLeft = 1 << 7, + // kPadBtnL2 = 1 << 8, + // kPadBtnR2 = 1 << 9, + // kPadBtnL1 = 1 << 10, + // kPadBtnR1 = 1 << 11, + // kPadBtnTriangle = 1 << 12, + // kPadBtnCircle = 1 << 13, + // kPadBtnCross = 1 << 14, + // kPadBtnSquare = 1 << 15, + // kPadBtnTouchPad = 1 << 20, + // kPadBtnIntercepted = 1 << 31, + // }; + auto args = *reinterpret_cast(argp); - ORBIS_LOG_ERROR("hid read state", args.hidId, args.unk0, args.unk1, - args.unk2, args.unk3, args.unk4, args.unk5); + // ORBIS_LOG_ERROR("hid read state", args.hidId, args.unk0, args.state, + // args.unk2, args.connected, args.unk4, args.unk5); + + auto state = (amdgpu::bridge::PadState *)args.state; + *state = rx::bridge.header->kbPadState; + *args.connected = 1; + *args.unk4 = 1; // is wireless? + thread->retval[0] = 1; + return {}; + } + + case 0x8010480e: { + // read information + ORBIS_LOG_ERROR("hid read information"); + return {}; } default: