From 88eb16ea429584959167fbbfbd55bbaadeef6217 Mon Sep 17 00:00:00 2001 From: Adrian <78108584+AdrianCassar@users.noreply.github.com> Date: Sat, 8 Jun 2024 13:58:22 +0100 Subject: [PATCH] [HID] Cleanup Keyboard Input (#15) Removed all mousehook specific code. --- src/xenia/app/emulator_window.cc | 6 +- src/xenia/app/xenia_main.cc | 8 +- src/xenia/base/profiling.cc | 40 - src/xenia/base/profiling.h | 14 +- src/xenia/emulator.cc | 144 +-- src/xenia/emulator.h | 7 - src/xenia/hid/input_driver.h | 2 + src/xenia/hid/input_system.cc | 7 + src/xenia/hid/input_system.h | 2 + src/xenia/hid/sdl/sdl_input_driver.cc | 6 +- src/xenia/hid/winkey/hookables/Crackdown2.cc | 149 --- src/xenia/hid/winkey/hookables/Crackdown2.h | 44 - .../hid/winkey/hookables/SourceEngine.cc | 269 ------ src/xenia/hid/winkey/hookables/SourceEngine.h | 61 -- src/xenia/hid/winkey/hookables/goldeneye.cc | 536 ----------- src/xenia/hid/winkey/hookables/goldeneye.h | 59 -- src/xenia/hid/winkey/hookables/halo3.cc | 206 ---- src/xenia/hid/winkey/hookables/halo3.h | 66 -- .../hid/winkey/hookables/hookable_game.h | 48 - src/xenia/hid/winkey/premake5.lua | 3 +- src/xenia/hid/winkey/winkey_input_driver.cc | 902 +++++++----------- src/xenia/hid/winkey/winkey_input_driver.h | 39 +- src/xenia/kernel/kernel_state.cc | 8 - src/xenia/kernel/kernel_state.h | 1 - src/xenia/kernel/xam/xam_ui.cc | 10 +- src/xenia/premake5.lua | 1 - src/xenia/ui/virtual_key.h | 2 + src/xenia/ui/window.cc | 50 - src/xenia/ui/window.h | 17 +- src/xenia/ui/window_listener.h | 1 - src/xenia/ui/window_win.cc | 223 ++--- src/xenia/ui/window_win.h | 1 - 32 files changed, 473 insertions(+), 2459 deletions(-) delete mode 100644 src/xenia/hid/winkey/hookables/Crackdown2.cc delete mode 100644 src/xenia/hid/winkey/hookables/Crackdown2.h delete mode 100644 src/xenia/hid/winkey/hookables/SourceEngine.cc delete mode 100644 src/xenia/hid/winkey/hookables/SourceEngine.h delete mode 100644 src/xenia/hid/winkey/hookables/goldeneye.cc delete mode 100644 src/xenia/hid/winkey/hookables/goldeneye.h delete mode 100644 src/xenia/hid/winkey/hookables/halo3.cc delete mode 100644 src/xenia/hid/winkey/hookables/halo3.h delete mode 100644 src/xenia/hid/winkey/hookables/hookable_game.h diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index 31f22204ac..05e43a81ba 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -299,11 +299,11 @@ void EmulatorWindow::EmulatorWindowListener::OnKeyDown(ui::KeyEvent& e) { } void EmulatorWindow::EmulatorWindowListener::OnMouseDown(ui::MouseEvent& e) { - //emulator_window_.OnMouseDown(e); + emulator_window_.OnMouseDown(e); } void EmulatorWindow::EmulatorWindowListener::OnMouseUp(ui::MouseEvent& e) { - //emulator_window_.OnMouseUp(e); + emulator_window_.OnMouseUp(e); } void EmulatorWindow::DisplayConfigGameConfigLoadCallback::PostGameConfigLoad() { @@ -1385,7 +1385,7 @@ void EmulatorWindow::SetFullscreen(bool fullscreen) { } window_->SetFullscreen(fullscreen); window_->SetCursorVisibility(fullscreen - ? ui::Window::CursorVisibility::kHidden + ? ui::Window::CursorVisibility::kAutoHidden : ui::Window::CursorVisibility::kVisible); } diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index 0e621e4e99..0a2dcdb26f 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -356,16 +356,16 @@ std::vector> EmulatorApp::CreateInputDrivers( xe::hid::nop::Create(window, EmulatorWindow::kZOrderHidInput)); } else { Factory factory; -#if XE_PLATFORM_WIN32 - // WinKey input driver should always be the last input driver added! - factory.Add("winkey", xe::hid::winkey::Create); -#endif // XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32 factory.Add("xinput", xe::hid::xinput::Create); #endif // XE_PLATFORM_WIN32 #if !XE_PLATFORM_ANDROID factory.Add("sdl", xe::hid::sdl::Create); #endif // !XE_PLATFORM_ANDROID +#if XE_PLATFORM_WIN32 + // WinKey input driver should always be the last input driver added! + factory.Add("winkey", xe::hid::winkey::Create); +#endif // XE_PLATFORM_WIN32 for (auto& driver : factory.CreateAll(cvars::hid, window, EmulatorWindow::kZOrderHidInput)) { if (XSUCCEEDED(driver->Setup())) { diff --git a/src/xenia/base/profiling.cc b/src/xenia/base/profiling.cc index f7964f1a80..a9ba9cc828 100644 --- a/src/xenia/base/profiling.cc +++ b/src/xenia/base/profiling.cc @@ -271,46 +271,6 @@ void Profiler::SetUserIO(size_t z_order, ui::Window* window, } #endif // XE_OPTION_PROFILING_UI } - - // Pass through mouse events. - window_->on_mouse_down.AddListener([](ui::MouseEvent& e) { - if (Profiler::is_visible()) { - Profiler::ProfilerWindowInputListener::OnMouseDown(e); - e.set_handled(true); - } - }); - window_->on_mouse_up.AddListener([](ui::MouseEvent& e) { - if (Profiler::is_visible()) { - Profiler::ProfilerWindowInputListener::OnMouseUp(e); - e.set_handled(true); - } - }); - window_->on_mouse_move.AddListener([](ui::MouseEvent& e) { - if (Profiler::is_visible()) { - Profiler::ProfilerWindowInputListener::OnMouseMove(e); - e.set_handled(true); - } - }); - window_->on_mouse_wheel.AddListener([](ui::MouseEvent& e) { - if (Profiler::is_visible()) { - Profiler::ProfilerWindowInputListener::OnMouseWheel(e); - e.set_handled(true); - } - }); - - // Watch for toggle/mode keys and such. - window_->on_key_down.AddListener([](ui::KeyEvent& e) { - if (Profiler::is_visible()) { - Profiler::ProfilerWindowInputListener::OnKeyDown(e); - e.set_handled(true); - } - }); - window_->on_key_up.AddListener([](ui::KeyEvent& e) { - if (Profiler::is_visible()) { - Profiler::ProfilerWindowInputListener::OnKeyUp(e); - e.set_handled(true); - } - }); } void Profiler::Flip() { diff --git a/src/xenia/base/profiling.h b/src/xenia/base/profiling.h index 7ac0284858..b754bcf318 100644 --- a/src/xenia/base/profiling.h +++ b/src/xenia/base/profiling.h @@ -20,7 +20,7 @@ #include "xenia/ui/virtual_key.h" #include "xenia/ui/window_listener.h" -#if XE_PLATFORM_WIN32 +#if XE_PLATFORM_WIN32 && 0 #define XE_OPTION_PROFILING 1 #define XE_OPTION_PROFILING_UI 1 #else @@ -204,13 +204,13 @@ class Profiler { #if XE_OPTION_PROFILING class ProfilerWindowInputListener final : public ui::WindowInputListener { public: - static void OnKeyDown(ui::KeyEvent& e); - static void OnKeyUp(ui::KeyEvent& e); + void OnKeyDown(ui::KeyEvent& e) override; + void OnKeyUp(ui::KeyEvent& e) override; #if XE_OPTION_PROFILING_UI - static void OnMouseDown(ui::MouseEvent& e); - static void OnMouseMove(ui::MouseEvent& e); - static void OnMouseUp(ui::MouseEvent& e); - static void OnMouseWheel(ui::MouseEvent& e); + void OnMouseDown(ui::MouseEvent& e) override; + void OnMouseMove(ui::MouseEvent& e) override; + void OnMouseUp(ui::MouseEvent& e) override; + void OnMouseWheel(ui::MouseEvent& e) override; #endif // XE_OPTION_PROFILING_UI }; // For now, no need for OnDpiChanged in a WindowListener because redrawing is diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index 918643d741..bce980f3ca 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -75,11 +75,6 @@ DEFINE_string( "or the module specified by the game. Leave blank to launch the default " "module.", "General"); - -DEFINE_bool(ge_remove_blur, false, - "(GoldenEye) Removes low-res blur when in classic-graphics mode", "MouseHook"); -DEFINE_bool(ge_debug_menu, false, - "(GoldenEye) Enables the debug menu, accessible with LB/1", "MouseHook"); DEFINE_bool(allow_game_relative_writes, false, "Not useful to non-developers. Allows code to write to paths " @@ -1366,7 +1361,6 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, title_id_ = std::nullopt; title_name_ = ""; title_version_ = ""; - executable_path_.clear(); display_window_->SetIcon(nullptr, 0); // Allow xam to request module loads. @@ -1390,9 +1384,6 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, XELOGE("Failed to initialize user module {}", path); return result; } - - executable_path_ = path; - // Grab the current title ID. xex2_opt_execution_info* info = nullptr; uint32_t workspace_address = 0; @@ -1507,139 +1498,6 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, } } } - - auto patch_addr = [module](uint32_t addr, uint32_t value) { - auto* patch_ptr = - (xe::be*)module->memory()->TranslateVirtual(addr); - auto heap = module->memory()->LookupHeap(addr); - - uint32_t old_protect = 0; - heap->Protect(addr, 4, kMemoryProtectRead | kMemoryProtectWrite, - &old_protect); - *patch_ptr = value; - heap->Protect(addr, 4, old_protect); - }; - - if (module->title_id() == 0x584109C2) { - // Prevent game from writing RS thumbstick to crosshair/gun position - // Multiple PD revisions so we'll need to search the code... - - std::vector search_insns = { - 0xD17F16A8, // stfs f11, 0x16A8(r31) - 0xD19F16A4, // stfs f12, 0x16A4(r31) - 0xD19F1690, // stfs f12, 0x1690(r31) - 0xD15F1694, // stfs f10, 0x1694(r31) - 0xD0FF0CFC, // stfs f7, 0xCFC(r31) - 0xD0BF0D00 // stfs f5, 0xD00(r31) - }; - - int patched = 0; - - auto* xex = module->xex_module(); - auto* check_addr = - (xe::be*)module->memory()->TranslateVirtual( - xex->base_address()); - auto* end_addr = (xe::be*)module->memory()->TranslateVirtual( - xex->base_address() + xex->image_size()); - - while (end_addr > check_addr) { - auto value = *check_addr; - - for (auto test : search_insns) { - if (test == value) { - uint32_t addr = module->memory()->HostToGuestVirtual(check_addr); - patch_addr(addr, 0x60000000); - patched++; - break; - } - } - - check_addr++; - } - } - - if (module->title_id() == 0x584108A9) { - struct GEPatchOffsets { - uint32_t check_addr; - uint32_t check_value; - - uint32_t crosshair_addr1; - uint32_t crosshair_patch1; - uint32_t crosshair_addr2; - uint32_t crosshair_patch2; - - uint32_t returnarcade_addr1; - uint32_t returnarcade_patch1; - uint32_t returnarcade_addr2; - uint32_t returnarcade_patch2; - uint32_t returnarcade_addr3; - uint32_t returnarcade_patch3; - - uint32_t blur_addr; - uint32_t debug_addr; - }; - - std::vector supported_builds = { - // Nov 2007 Release build - {0x8200336C, 0x676f6c64, 0x820A45D0, 0x4800003C, 0x820A46D4, - 0x4800003C, 0x820F7750, 0x2F1E0007, 0x820F7D04, 0x2F1A0007, - 0x820F7780, 0x2B0A0003, 0x82188E70, 0x82189F28}, - - // Nov 2007 Team build - {0x82003398, 0x676f6c64, 0x820C85B0, 0x480000B0, 0x820C88B8, - 0x480000B0, 0x8213ABE8, 0x2F0B0007, 0x8213AF0C, 0x2F0B0007, - 0x8213ACB4, 0x2B0B0004, 0x8221DF34, 0}, - - // Nov 2007 Debug build - {0x82005540, 0x676f6c64, 0x822A2BFC, 0x480000B0, 0x822A2F04, - 0x480000B0, 0x82344D04, 0x2F0B0007, 0x82345030, 0x2F0B0007, - 0x82344DD0, 0x2B0B0004, 0x824AB510, 0}, - }; - - for (auto& build : supported_builds) { - auto* test_addr = - (xe::be*)module->memory()->TranslateVirtual( - build.check_addr); - if (*test_addr != build.check_value) { - continue; - } - - // Prevent game from overwriting crosshair/gun positions - if (build.crosshair_addr1) { - patch_addr(build.crosshair_addr1, build.crosshair_patch1); - } - if (build.crosshair_addr2) { - patch_addr(build.crosshair_addr2, build.crosshair_patch2); - } - - // Hide "return to arcade" menu option - if (build.returnarcade_addr1) { - patch_addr(build.returnarcade_addr1, build.returnarcade_patch1); - } - if (build.returnarcade_addr2) { - patch_addr(build.returnarcade_addr2, build.returnarcade_patch2); - } - // Prevent "return to arcade" code from being executed - if (build.returnarcade_addr3) { - patch_addr(build.returnarcade_addr3, build.returnarcade_patch3); - } - - if (cvars::ge_remove_blur && build.blur_addr) { - // Patch out N64 blur - // Source: - // https://github.com/xenia-canary/game-patches/blob/main/patches/584108A9.patch - - patch_addr(build.blur_addr, 0x60000000); - } - - if (cvars::ge_debug_menu && build.debug_addr) { - // Enable debug menu - patch_addr(build.debug_addr, 0x2B0B0000); - } - - break; - } - } // Initializing the shader storage in a blocking way so the user doesn't // miss the initial seconds - for instance, sound from an intro video may @@ -1657,6 +1515,8 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, main_thread_ = main_thread; on_launch(title_id_.value(), title_name_); + input_system()->UpdateTitleId(title_id_.value()); + // Plugins must be loaded after calling LaunchModule() and // FinishLoadingUserModule() which will apply TUs and patching to the main // xex. diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h index a1cb69a3a2..6bc037759f 100644 --- a/src/xenia/emulator.h +++ b/src/xenia/emulator.h @@ -116,11 +116,6 @@ class Emulator { // Version of the title as a string. const std::string& title_version() const { return title_version_; } - - // Host path of the executable being ran - const std::filesystem::path& executable_path() const { - return executable_path_; - } // Currently running title ID uint32_t title_id() const { @@ -301,8 +296,6 @@ class Emulator { std::filesystem::path storage_root_; std::filesystem::path content_root_; std::filesystem::path cache_root_; - - std::filesystem::path executable_path_; std::string title_name_; std::string title_version_; diff --git a/src/xenia/hid/input_driver.h b/src/xenia/hid/input_driver.h index 6b0ff34727..a23ce33071 100644 --- a/src/xenia/hid/input_driver.h +++ b/src/xenia/hid/input_driver.h @@ -46,6 +46,8 @@ class InputDriver { is_active_callback_ = is_active_callback; } + uint32_t title_id = 0; + protected: explicit InputDriver(xe::ui::Window* window, size_t window_z_order) : window_(window), window_z_order_(window_z_order) {} diff --git a/src/xenia/hid/input_system.cc b/src/xenia/hid/input_system.cc index d414c7bc5d..01de7f4fff 100644 --- a/src/xenia/hid/input_system.cc +++ b/src/xenia/hid/input_system.cc @@ -243,6 +243,13 @@ X_INPUT_VIBRATION InputSystem::ModifyVibrationLevel( modified_vibration.right_motor_speed = 0; return modified_vibration; } + +void InputSystem::UpdateTitleId(uint32_t title_id) { + for (auto& driver : drivers_) { + driver->title_id = title_id; + } +} + std::unique_lock InputSystem::lock() { return std::unique_lock{lock_}; } diff --git a/src/xenia/hid/input_system.h b/src/xenia/hid/input_system.h index b1c0db52d5..ad14f30805 100644 --- a/src/xenia/hid/input_system.h +++ b/src/xenia/hid/input_system.h @@ -55,6 +55,8 @@ class InputSystem { uint32_t GetLastUsedSlot() const { return last_used_slot; } + void UpdateTitleId(uint32_t title_id); + std::unique_lock lock(); private: diff --git a/src/xenia/hid/sdl/sdl_input_driver.cc b/src/xenia/hid/sdl/sdl_input_driver.cc index 12e0be8d66..d0bd0ca93d 100644 --- a/src/xenia/hid/sdl/sdl_input_driver.cc +++ b/src/xenia/hid/sdl/sdl_input_driver.cc @@ -398,7 +398,7 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags, if (!(butts_changed & fbutton)) { continue; } - ui::VirtualKey vk = kVkLookup.at(last.repeat_butt_idx); + ui::VirtualKey vk = kVkLookup.at(i); if (vk == ui::VirtualKey::kNone) { continue; } @@ -637,9 +637,9 @@ void SDLInputDriver::OnControllerDeviceButtonChanged(const SDL_Event& event) { if (xbutton == X_INPUT_GAMEPAD_GUIDE && !cvars::guide_button) { return; } - xbuttons |= (uint16_t)xbutton; + xbuttons |= xbutton; } else { - xbuttons &= ~(uint16_t)xbutton; + xbuttons &= ~xbutton; } controller.state.gamepad.buttons = xbuttons; controller.state_changed = true; diff --git a/src/xenia/hid/winkey/hookables/Crackdown2.cc b/src/xenia/hid/winkey/hookables/Crackdown2.cc deleted file mode 100644 index 6770f439a6..0000000000 --- a/src/xenia/hid/winkey/hookables/Crackdown2.cc +++ /dev/null @@ -1,149 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2023 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#define _USE_MATH_DEFINES - -#include "xenia/hid/winkey/hookables/Crackdown2.h" - -#include "xenia/base/platform_win.h" -#include "xenia/cpu/processor.h" -#include "xenia/emulator.h" -#include "xenia/hid/hid_flags.h" -#include "xenia/hid/input_system.h" -#include "xenia/kernel/util/shim_utils.h" -#include "xenia/kernel/xmodule.h" -#include "xenia/kernel/xthread.h" -#include "xenia/xbox.h" - -using namespace xe::kernel; - -DECLARE_double(sensitivity); -DECLARE_bool(invert_y); -DECLARE_bool(invert_x); - -const uint32_t kTitleIdCrackdown2 = 0x4D5308BC; - -namespace xe { -namespace hid { -namespace winkey { -struct GameBuildAddrs { - uint32_t base_address; - std::string title_version; - uint32_t x_offset; - uint32_t y_offset; -}; - -std::map supported_builds{ - {Crackdown2Game::GameBuild::Crackdown2_TU0, {0x836C6520, "1.0", 0x7EC, 0x7E8}}, - {Crackdown2Game::GameBuild::Crackdown2_TU5, {0x83800F88, "1.0.5", 0x7EC, 0x7E8}}}; - -Crackdown2Game::~Crackdown2Game() = default; - -bool Crackdown2Game::IsGameSupported() { - if (kernel_state()->title_id() != kTitleIdCrackdown2) { - return false; - } - - const std::string current_version = - kernel_state()->emulator()->title_version(); - - for (auto& build : supported_builds) { - if (current_version == build.second.title_version) { - game_build_ = build.first; - return true; - } - } - - return false; -} - -float Crackdown2Game::DegreetoRadians(float degree) { - return (float)(degree * (M_PI / 180)); -} - -float Crackdown2Game::RadianstoDegree(float radians) { - return (float)(radians * (180 / M_PI)); -} - -bool Crackdown2Game::DoHooks(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state) { - if (!IsGameSupported()) { - return false; - } - - if (supported_builds.count(game_build_) == 0) { - return false; - } - - // Don't constantly write if there is no mouse movement. - if (input_state.mouse.x_delta == 0 || input_state.mouse.y_delta == 0) { - return false; - } - - XThread* current_thread = XThread::GetCurrentThread(); - - if (!current_thread) { - return false; - } - - xe::be* base_address = - kernel_memory()->TranslateVirtual*>( - supported_builds[game_build_].base_address); - - if (!base_address || *base_address == NULL) { - // Not in game - return false; - } - - xe::be x_address = - *base_address + supported_builds[game_build_].x_offset; - xe::be y_address = - *base_address + supported_builds[game_build_].y_offset; - - xe::be* radian_x = - kernel_memory()->TranslateVirtual*>(x_address); - - xe::be* radian_y = - kernel_memory()->TranslateVirtual*>(y_address); - - float degree_x = RadianstoDegree(*radian_x); - float degree_y = RadianstoDegree(*radian_y); - - // X-axis = 0 to 360 - if (!cvars::invert_x) - { - degree_x += (input_state.mouse.x_delta / 50.f) * (float)cvars::sensitivity; - *radian_x = DegreetoRadians(degree_x); - } - else - { - degree_x -= (input_state.mouse.x_delta / 50.f) * (float)cvars::sensitivity; - *radian_x = DegreetoRadians(degree_x); - } - - // Y-axis = -90 to 90 - if (!cvars::invert_y) { - degree_y += (input_state.mouse.y_delta / 50.f) * (float)cvars::sensitivity; - } else { - degree_y -= (input_state.mouse.y_delta / 50.f) * (float)cvars::sensitivity; - } - - *radian_y = DegreetoRadians(degree_y); - - return true; -} - -bool Crackdown2Game::ModifierKeyHandler(uint32_t user_index, - RawInputState& input_state, - X_INPUT_STATE* out_state) { - return false; -} -} // namespace winkey -} // namespace hid -} // namespace xe \ No newline at end of file diff --git a/src/xenia/hid/winkey/hookables/Crackdown2.h b/src/xenia/hid/winkey/hookables/Crackdown2.h deleted file mode 100644 index 43418c94d1..0000000000 --- a/src/xenia/hid/winkey/hookables/Crackdown2.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2023 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_HID_WINKEY_Crackdown2_H_ -#define XENIA_HID_WINKEY_Crackdown2_H_ - -#include "xenia/hid/winkey/hookables/hookable_game.h" - -namespace xe { -namespace hid { -namespace winkey { - -class Crackdown2Game : public HookableGame { - public: - enum class GameBuild { Unknown, Crackdown2_TU0, Crackdown2_TU5 }; - - ~Crackdown2Game() override; - - bool IsGameSupported(); - - float RadianstoDegree(float radians); - float DegreetoRadians(float degree); - - bool DoHooks(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state); - - bool ModifierKeyHandler(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state); - - private: - GameBuild game_build_ = GameBuild::Unknown; -}; - -} // namespace winkey -} // namespace hid -} // namespace xe - -#endif // XENIA_HID_WINKEY_Crackdown2_H_ diff --git a/src/xenia/hid/winkey/hookables/SourceEngine.cc b/src/xenia/hid/winkey/hookables/SourceEngine.cc deleted file mode 100644 index 51718da824..0000000000 --- a/src/xenia/hid/winkey/hookables/SourceEngine.cc +++ /dev/null @@ -1,269 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2023 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/hid/winkey/hookables/SourceEngine.h" - -#include "xenia/base/platform_win.h" -#include "xenia/cpu/processor.h" -#include "xenia/emulator.h" -#include "xenia/hid/hid_flags.h" -#include "xenia/hid/input_system.h" -#include "xenia/kernel/util/shim_utils.h" -#include "xenia/kernel/xmodule.h" -#include "xenia/kernel/xthread.h" -#include "xenia/xbox.h" - -using namespace xe::kernel; - -DECLARE_double(sensitivity); -DECLARE_double(source_sniper_sensitivity); -DECLARE_bool(invert_y); -DECLARE_bool(invert_x); -DECLARE_int32(walk_orthogonal); -DECLARE_int32(walk_diagonal); - -const uint32_t kTitleIdCSGO = 0x5841125A; -const uint32_t kTitleIdL4D1 = 0x45410830; -const uint32_t kTitleIdL4D2 = 0x454108D4; -const uint32_t kTitleIdOrangeBox = 0x4541080F; -const uint32_t kTitleIdPortalSA = 0x58410960; -const uint32_t kTitleIdPortal2 = 0x45410912; - -namespace xe { -namespace hid { -namespace winkey { - -bool __inline IsKeyToggled(uint8_t key) { - return (GetKeyState(key) & 0x1) == 0x1; -} - -SourceEngine::SourceEngine() { - original_sensitivity = cvars::sensitivity; - engine_360 = NULL; -}; - -SourceEngine::~SourceEngine() = default; - -struct GameBuildAddrs { - uint32_t title_id; - std::string title_version; - uint32_t execute_addr; - uint32_t angle_offset; -}; - -// Replace with build names when we introduce more compatibility -std::map supported_builds{ - { - SourceEngine::GameBuild::CSGO, - {kTitleIdCSGO, "5.0", 0x86955490, 0x4AE8} - }, - { - SourceEngine::GameBuild::CSGO_Beta, - {kTitleIdCSGO, "1.0.1.16", 0x8697DB30, 0x4AC8} - }, - { - SourceEngine::GameBuild::L4D1, - {kTitleIdL4D1, "1.0", 0x86536888, 0x4B44} - }, - { - SourceEngine::GameBuild::L4D1_GOTY, - {kTitleIdL4D1, "6.0", 0x86537FA0, 0x4B44} - }, - { - SourceEngine::GameBuild::L4D2, - {kTitleIdL4D2, "3.0", 0x86CC4E60, 0x4A94} - }, - { - SourceEngine::GameBuild::OrangeBox, - {kTitleIdOrangeBox, "4.0", NULL, 0x863F53A8} - }, - { - SourceEngine::GameBuild::PortalSA, - {kTitleIdPortalSA, "3.0.1", NULL, 0x863F56B0} - }, - { - SourceEngine::GameBuild::Portal2, - {kTitleIdPortal2, "4.0", 0x82C50180, 0x4A98} - }, - { - SourceEngine::GameBuild::Portal2_TU1, - {kTitleIdPortal2, "4.0.1", 0x82C50220, 0x4A98} - } -}; - -bool SourceEngine::IsGameSupported() { - auto title_id = kernel_state()->title_id(); - if (title_id != kTitleIdCSGO && title_id != kTitleIdL4D1 && title_id != kTitleIdL4D2 && title_id != kTitleIdOrangeBox && title_id != kTitleIdPortalSA && title_id != kTitleIdPortal2) - return false; - - const std::string current_version = - kernel_state()->emulator()->title_version(); - - for (auto& build : supported_builds) - { - if (title_id == build.second.title_id && current_version == build.second.title_version) - { - game_build_ = build.first; - return true; - } - } - - return false; -} - -#define IS_KEY_DOWN(x) (input_state.key_states[x]) - -bool SourceEngine::DoHooks(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state) { - if (!IsGameSupported()) { - return false; - } - - // Wait until module is loaded, if loaded don't check again otherwise it will - // impact performance. - if (!engine_360) { - if (!kernel_state()->GetModule("engine_360.dll")) { - return false; - } else { - engine_360 = true; - } - } - - XThread* current_thread = XThread::GetCurrentThread(); - - if (!current_thread) { - return false; - } - - uint32_t player_ptr; - if (supported_builds[game_build_].execute_addr) - { - current_thread->thread_state()->context()->r[3] = -1; - - kernel_state()->processor()->Execute( - current_thread->thread_state(), - supported_builds[game_build_].execute_addr); - - // Get player pointer - player_ptr = - static_cast(current_thread->thread_state()->context()->r[3]); - - if (!player_ptr) { - // Not in game - return false; - } - } - - xe::be* angle_offset; - - if (supported_builds[game_build_].execute_addr) - { - angle_offset = kernel_memory()->TranslateVirtual*>( - player_ptr + supported_builds[game_build_].angle_offset); - } - else - { - angle_offset = kernel_memory()->TranslateVirtual*>(supported_builds[game_build_].angle_offset); - } - - QAngle* ang = reinterpret_cast(angle_offset); - - // std::string angState = fmt::format("Angle: y: {} x: {} z: {}", ang->pitchY, - // ang->pitchX, ang->yaw); - - // Have to do weird things converting it to normal float otherwise - // xe::be += treats things as int? - float camX = (float)ang->pitchX; - float camY = (float)ang->pitchY; - - if (cvars::source_sniper_sensitivity != 0) { - if (IsKeyToggled(VK_CAPITAL) != 0) { - cvars::sensitivity = cvars::source_sniper_sensitivity; - } else { - cvars::sensitivity = original_sensitivity; - } - } - - if (!cvars::invert_x) - { - camX -= - (((float)input_state.mouse.x_delta) / 7.5f) * (float)cvars::sensitivity; - } - else - { - camX += - (((float)input_state.mouse.x_delta) / 7.5f) * (float)cvars::sensitivity; - } - - if (!cvars::invert_y) { - camY += - (((float)input_state.mouse.y_delta) / 7.5f) * (float)cvars::sensitivity; - } else { - camY -= - (((float)input_state.mouse.y_delta) / 7.5f) * (float)cvars::sensitivity; - } - - ang->pitchX = camX; - ang->pitchY = camY; - - return true; -} - -// probably making a mistake using a template, ah well -template int sgn(T val) -{ - return (T(0) < val) - (val < T(0)); -} - -bool SourceEngine::ModifierKeyHandler(uint32_t user_index, - RawInputState& input_state, - X_INPUT_STATE* out_state) -{ - float thumb_lx = (int16_t)out_state->gamepad.thumb_lx; - float thumb_ly = (int16_t)out_state->gamepad.thumb_ly; - - // Work out angle from the current stick values - float angle = atan2f(thumb_ly, thumb_lx); - - // Equates to 134.99 h.u./s - 22800 for forward/backward, 18421 for diagonal - int16_t distance_x, distance_y; - - // as soon as you put it to a separate variable it stops bugging out - - int multiplier_x = sgn(thumb_lx); - int multiplier_y = sgn(thumb_ly); - - // If angle DIV π⁄4 is odd - if (fmod(angle / 0.785398185f, 2) != 0) - { - distance_x = int16_t(cvars::walk_diagonal * multiplier_x); - distance_y = int16_t(cvars::walk_diagonal * multiplier_y); - } - else - { - // Default value equates to 134.99 h.u./s, any higher than this value and the movement speed immediately goes to max - distance_x = int16_t(cvars::walk_orthogonal * multiplier_x); // Default value between SHRT_MAX * (177.4/255 and 177.5/255) - distance_y = int16_t(cvars::walk_orthogonal * multiplier_y); // Default value between SHRT_MAX * (177.4/255 and 177.5/255) - } - - // Need analogue-compatible version - //out_state->gamepad.thumb_lx = (int16_t)(distance * cosf(angle)); - //out_state->gamepad.thumb_ly = (int16_t)(distance * sinf(angle)); - out_state->gamepad.thumb_lx = distance_x; - out_state->gamepad.thumb_ly = distance_y; - - // Return true to signal that we've handled the modifier, so default modifier won't be used - return true; - - -} - -} // namespace winkey -} // namespace hid -} // namespace xe diff --git a/src/xenia/hid/winkey/hookables/SourceEngine.h b/src/xenia/hid/winkey/hookables/SourceEngine.h deleted file mode 100644 index e2a3d01574..0000000000 --- a/src/xenia/hid/winkey/hookables/SourceEngine.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2023 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_HID_WINKEY_SOURCE_ENGINE_H_ -#define XENIA_HID_WINKEY_SOURCE_ENGINE_H_ - -#include "xenia/hid/winkey/hookables/hookable_game.h" - -namespace xe { -namespace hid { -namespace winkey { - -class SourceEngine : public HookableGame { - public: - enum class GameBuild { - Unknown, - CSGO, - CSGO_Beta, - L4D1, - L4D1_GOTY, - L4D2, - OrangeBox, - PortalSA, - Portal2, - Portal2_TU1 - }; - - SourceEngine(); - ~SourceEngine() override; - - bool IsGameSupported(); - bool DoHooks(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state); - bool ModifierKeyHandler(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state); - - private: - GameBuild game_build_ = GameBuild::Unknown; - - struct QAngle { - xe::be pitchY; - xe::be pitchX; - xe::be yaw; - }; - - bool engine_360; - - double original_sensitivity; -}; - -} // namespace winkey -} // namespace hid -} // namespace xe - -#endif // XENIA_HID_WINKEY_CSGO_H_ diff --git a/src/xenia/hid/winkey/hookables/goldeneye.cc b/src/xenia/hid/winkey/hookables/goldeneye.cc deleted file mode 100644 index 56afef8c43..0000000000 --- a/src/xenia/hid/winkey/hookables/goldeneye.cc +++ /dev/null @@ -1,536 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/hid/winkey/hookables/goldeneye.h" - -#include "xenia/base/platform_win.h" -#include "xenia/hid/hid_flags.h" -#include "xenia/hid/input_system.h" -#include "xenia/kernel/util/shim_utils.h" -#include "xenia/xbox.h" - -using namespace xe::kernel; - -DECLARE_double(sensitivity); -DECLARE_bool(invert_y); -DECLARE_bool(invert_x); -DECLARE_bool(disable_autoaim); - -DEFINE_double(ge_aim_turn_distance, 0.4f, - "(GoldenEye/Perfect Dark) Distance crosshair can move in aim-mode before " - "turning the camera [range 0 - 1]", - "MouseHook"); - -DEFINE_double(ge_menu_sensitivity, 0.5f, - "(GoldenEye) Mouse sensitivity when in menus", "MouseHook"); - -DEFINE_bool(ge_gun_sway, true, "(GoldenEye/Perfect Dark) Enable gun sway as camera is turned", - "MouseHook"); - -const uint32_t kTitleIdGoldenEye = 0x584108A9; -const uint32_t kTitleIdPerfectDark = 0x584109C2; - -namespace xe { -namespace hid { -namespace winkey { - -GoldeneyeGame::~GoldeneyeGame() = default; - -struct RareGameBuildAddrs { - uint32_t check_addr; // addr to check - uint32_t check_value; // value to look for, if matches this value we know - // it's this game - - uint32_t menu_addr; // addr of menu x/y - uint32_t game_pause_addr; - - uint32_t settings_addr; - uint32_t settings_bitflags_offset; - - uint32_t player_addr; // addr to pointer of player data - - uint32_t player_offset_watch_status; // some watch-status counter, if non-zero then game is paused - uint32_t player_offset_disabled; // offset to "is control disabled" flag - uint32_t player_offset_cam_x; // offset to camera X pos - uint32_t player_offset_cam_y; // offset to camera Y pos - uint32_t player_offset_crosshair_x; - uint32_t player_offset_crosshair_y; - uint32_t player_offset_gun_x; - uint32_t player_offset_gun_y; - uint32_t player_offset_aim_mode; - uint32_t player_offset_aim_multiplier; -}; - -std::map supported_builds = { - // GoldenEye Nov2007 build (aka Aug2007 build) - { - GoldeneyeGame::GameBuild::GoldenEye_Nov2007_Release, - {0x8200336C, 0x676f6c64, 0x8272B37C, 0x82F1E70C, 0x83088228, 0x298, 0x82F1FA98, - 0x2E8, 0x80, 0x254, 0x264, 0x10A8, 0x10AC, 0x10BC, 0x10C0, 0x22C, - 0x11AC} - }, - { - GoldeneyeGame::GameBuild::GoldenEye_Nov2007_Team, - {0x82003398, 0x676f6c64, 0x827DB384, 0x82FCE6CC, 0x831382D0, 0x2A0, 0x82FCFA98, - 0x2E8, 0x80, 0x254, 0x264, 0x10A8, 0x10AC, 0x10BC, 0x10C0, 0x22C, - 0x11AC} - }, - // TODO: unsure about 83A4EABC - { - GoldeneyeGame::GameBuild::GoldenEye_Nov2007_Debug, - {0x82005540, 0x676f6c64, 0x830C8564, 0x83A4EABC, 0x83BFC018, 0x2A0, 0x83A50298, - 0x2E8, 0x80, 0x254, 0x264, 0x10A8, 0x10AC, 0x10BC, 0x10C0, 0x22C, - 0x11AC} - }, - - // PD: player_offset_disabled seems to be stored at 0x0 - // PD TODO: 0x104 almost seems like a good player_watch_status, but - // unfortunately gets triggered when health bar appears... - { - GoldeneyeGame::GameBuild::PerfectDark_Devkit_33, - {0x825CBC59, 0x30303333, 0, 0, 0x82620E08, 0, 0x826284C4, 0x1A4C, 0x0, 0x14C, - 0x15C, 0x1690, 0x1694, 0xCFC, 0xD00, 0x128, 0} - }, - { - GoldeneyeGame::GameBuild::PerfectDark_Release_52, - {0x825EC0E5, 0x30303532, 0, 0, 0x826419C0, 0, 0x8264909C, 0x1A4C, 0x0, 0x14C, - 0x15C, 0x1690, 0x1694, 0xCFC, 0xD00, 0x128, 0} - }, - { - GoldeneyeGame::GameBuild::PerfectDark_Devkit_102, - {0x825EC0E5, 0x30313032, 0, 0, 0x82641A80, 0, 0x82649274, 0x1A4C, 0x0, 0x14C, - 0x15C, 0x1690, 0x1694, 0xCFC, 0xD00, 0x128, 0} - }, - // TODO: test these! - /* - { - GoldeneyeGame::GameBuild::PerfectDark_Release_104, - {0x825EC0D5, 0x30313034, 0, 0, 0x82641A80, 0, 0x82649264, 0x1A4C, 0x0, 0x14C, - 0x15C, 0x1690, 0x1694, 0xCFC, 0xD00, 0x128, 0} - }, - { - GoldeneyeGame::GameBuild::PerfectDark_Release_107, - {0x825FC25D, 0x30313037, 0, 0, 0x8265A200, 0, 0x826619E4, 0x1A4C, 0x0, 0x14C, - 0x15C, 0x1690, 0x1694, 0xCFC, 0xD00, 0x128, 0} - },*/ -}; - -bool GoldeneyeGame::IsGameSupported() { - auto title_id = kernel_state()->title_id(); - - if (title_id != kTitleIdGoldenEye && title_id != kTitleIdPerfectDark) { - return false; - } - - for (auto& build : supported_builds) { - auto* build_ptr = kernel_memory()->TranslateVirtual*>( - build.second.check_addr); - - if (*build_ptr == build.second.check_value) { - game_build_ = build.first; - return true; - } - } - - return false; -} - -#define IS_KEY_DOWN(x) (input_state.key_states[x]) - -bool GoldeneyeGame::DoHooks(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state) { - if (!IsGameSupported()) { - return false; - } - - auto& game_addrs = supported_builds[game_build_]; - - // Move menu selection crosshair - // TODO: detect if we're actually in the menu first - if (game_addrs.menu_addr) { - auto menuX_ptr = - kernel_memory()->TranslateVirtual*>(game_addrs.menu_addr); - auto menuY_ptr = - kernel_memory()->TranslateVirtual*>(game_addrs.menu_addr + 4); - if (menuX_ptr && menuY_ptr) { - float menuX = *menuX_ptr; - float menuY = *menuY_ptr; - - menuX += (((float)input_state.mouse.x_delta) / 5.f) * - (float)cvars::ge_menu_sensitivity; - menuY += (((float)input_state.mouse.y_delta) / 5.f) * - (float)cvars::ge_menu_sensitivity; - - *menuX_ptr = menuX; - *menuY_ptr = menuY; - } - } - - // Read addr of player base - auto players_addr = - *kernel_memory()->TranslateVirtual*>(game_addrs.player_addr); - - if (!players_addr) { - return true; - } - - auto* player = kernel_memory()->TranslateVirtual(players_addr); - - uint32_t game_pause_flag = 0; - if (game_addrs.game_pause_addr) { - game_pause_flag = *kernel_memory()->TranslateVirtual*>( - game_addrs.game_pause_addr); - } - - // First check if control-disabled flag is set (eg. we're in a cutscene) - uint32_t game_control_disabled = 0; - game_control_disabled = - *(xe::be*)(player + game_addrs.player_offset_disabled); - - // Disable camera if watch is being brought up/lowered - if (game_control_disabled == 0 && game_addrs.player_offset_watch_status) { - // non-zero watch_status seems to disable controller inputs, so we'll do the same - game_control_disabled = - *(xe::be*)(player + game_addrs.player_offset_watch_status); - } - - // Disable auto-aim & lookahead - // (only if we detect game_control_active or game_pause_flag values are changing) - if (game_pause_flag != prev_game_pause_flag_ || - game_control_disabled != prev_game_control_disabled_) { - - if (game_addrs.settings_addr) { - auto settings_ptr = - kernel_memory()->TranslateVirtual*>( - game_addrs.settings_addr); - - if (*settings_ptr) { - - // GE points to settings struct which gets allocated somewhere random in memory - // PD's settings always seem to be in .data section though - if (game_build_ == GameBuild::GoldenEye_Nov2007_Release || - game_build_ == GameBuild::GoldenEye_Nov2007_Team || - game_build_ == GameBuild::GoldenEye_Nov2007_Debug) { - settings_ptr = kernel_memory()->TranslateVirtual*>( - *settings_ptr + game_addrs.settings_bitflags_offset); - uint32_t settings = *settings_ptr; - - enum GESettingFlag { - LookUpright = 0x8, // non-inverted - AutoAim = 0x10, - AimControlToggle = 0x20, - ShowAimCrosshair = 0x40, - LookAhead = 0x80, - ShowAmmoCounter = 0x100, - ShowAimBorder = 0x200, - ScreenLetterboxWide = 0x400, - ScreenLetterboxCinema = 0x800, - ScreenRatio16_9 = 0x1000, - ScreenRatio16_10 = 0x2000, - CameraRoll = 0x40000 - }; - - // Disable AutoAim & LookAhead - if (settings & GESettingFlag::LookAhead) { - settings = settings & ~((uint32_t)GESettingFlag::LookAhead); - } - if (cvars::disable_autoaim && (settings & GESettingFlag::AutoAim)) { - settings = settings & ~((uint32_t)GESettingFlag::AutoAim); - } - *settings_ptr = settings; - } else { - uint32_t settings = *settings_ptr; - - enum PDSettingFlag { - ReversePitch = 0x1, - LookAhead = 0x2, - SightOnScreen = 0x4, - AutoAim = 0x8, - AimControlToggle = 0x10, - AmmoOnScreen = 0x20, - ShowGunFunction = 0x40, - HeadRoll = 0x80, - InGameSubtitles = 0x100, - AlwaysShowTarget = 0x200, - ShowZoomRange = 0x400, - Paintball = 0x800, - CutsceneSubtitles = 0x1000, - ShowCrouch = 0x2000, - ShowMissionTime = 0x8000, - }; - - // Disable AutoAim & LookAhead - if (settings & PDSettingFlag::LookAhead) { - settings = settings & ~((uint32_t)PDSettingFlag::LookAhead); - } - if (cvars::disable_autoaim && (settings & PDSettingFlag::AutoAim)) { - settings = settings & ~((uint32_t)PDSettingFlag::AutoAim); - } - *settings_ptr = settings; - } - } - - prev_game_pause_flag_ = game_pause_flag; - prev_game_control_disabled_ = game_control_disabled; - } - } - - if (game_control_disabled) { - return true; - } - - // GE007 mousehook hax - xe::be* player_cam_x = (xe::be*)(player + game_addrs.player_offset_cam_x); - xe::be* player_cam_y = - (xe::be*)(player + game_addrs.player_offset_cam_y); - - xe::be* player_crosshair_x = - (xe::be*)(player + game_addrs.player_offset_crosshair_x); - xe::be* player_crosshair_y = - (xe::be*)(player + game_addrs.player_offset_crosshair_y); - xe::be* player_gun_x = - (xe::be*)(player + game_addrs.player_offset_gun_x); - xe::be* player_gun_y = - (xe::be*)(player + game_addrs.player_offset_gun_y); - - uint32_t player_aim_mode = - *(xe::be*)(player + game_addrs.player_offset_aim_mode); - - if (player_aim_mode != prev_aim_mode_) { - if (player_aim_mode != 0) { - // Entering aim mode, reset gun position - *player_gun_x = 0; - *player_gun_y = 0; - } - // Always reset crosshair after entering/exiting aim mode - // Otherwise non-aim-mode will still fire toward it... - *player_crosshair_x = 0; - *player_crosshair_y = 0; - prev_aim_mode_ = player_aim_mode; - } - - // TODO: try and eliminate some of these... - float bounds = 1; // screen bounds of gun/crosshair - float dividor = 500.f; - float gun_multiplier = 1; - float crosshair_multiplier = 1; - float centering_multiplier = 1; - - float aim_turn_distance = (float)cvars::ge_aim_turn_distance; - float aim_turn_dividor = 1.f; - - if (game_build_ != GameBuild::GoldenEye_Nov2007_Release && - game_build_ != GameBuild::GoldenEye_Nov2007_Team && - game_build_ != GameBuild::GoldenEye_Nov2007_Debug) { - // PD uses a different coordinate system to GE for some reason - // Following are best guesses for getting it to feel right: - bounds = 30.f; - dividor = 16.f; - gun_multiplier = 0.25f; - crosshair_multiplier = 4; - centering_multiplier = 25; - aim_turn_distance *= 30; - aim_turn_dividor = 20.f; - } - - if (player_aim_mode == 1) { - float chX = *player_crosshair_x; - float chY = *player_crosshair_y; - - if (!cvars::invert_x) - { - chX += (((float)input_state.mouse.x_delta) / dividor) * - (float)cvars::sensitivity; - } - else - { - chX -= (((float)input_state.mouse.x_delta) / dividor) * - (float)cvars::sensitivity; - } - - if (!cvars::invert_y) { - chY += (((float)input_state.mouse.y_delta) / dividor) * - (float)cvars::sensitivity; - } else { - chY -= (((float)input_state.mouse.y_delta) / dividor) * - (float)cvars::sensitivity; - } - - // Keep the gun/crosshair in-bounds [1:-1] - chX = std::min(chX, bounds); - chX = std::max(chX, -bounds); - chY = std::min(chY, bounds); - chY = std::max(chY, -bounds); - - *player_crosshair_x = chX; - *player_crosshair_y = chY; - *player_gun_x = (chX * gun_multiplier); - *player_gun_y = (chY * gun_multiplier); - - // Turn camera when crosshair is past a certain point - float camX = (float)*player_cam_x; - float camY = (float)*player_cam_y; - - // this multiplier lets us slow down the camera-turn when zoomed in - // value from this addr works but doesn't seem correct, seems too slow - // when zoomed, might be better to calculate it from FOV instead? - // (current_fov seems to be at 0x115C) - float aim_multiplier = 1; - if (game_addrs.player_offset_aim_multiplier) { - aim_multiplier = *reinterpret_cast*>( - player + game_addrs.player_offset_aim_multiplier); - } - - // TODO: This almost matches up with "show aim border" perfectly - // Except 0.4f will make Y move a little earlier than it should - // > 0.5f seems to work for Y, but then X needs to be moved further than - // it should need to... - - // TODO: see if we can find the algo the game itself uses - float ch_distance = sqrtf((chX * chX) + (chY * chY)); - if (ch_distance > aim_turn_distance) { - camX += ((chX / aim_turn_dividor) * aim_multiplier); - *player_cam_x = camX; - camY -= ((chY / aim_turn_dividor) * aim_multiplier); - *player_cam_y = camY; - } - - start_centering_ = true; - disable_sway_ = true; // skip weapon sway until we've centered - centering_speed_ = 0.05f; // speed up centering from aim-mode - } else { - float gX = *player_gun_x; - float gY = *player_gun_y; - - // Apply gun-centering - if (start_centering_) { - if (gX != 0 || gY != 0) { - if (gX > 0) { - gX -= std::min((centering_speed_ * centering_multiplier), gX); - } - if (gX < 0) { - gX += std::min((centering_speed_ * centering_multiplier), -gX); - } - if (gY > 0) { - gY -= std::min((centering_speed_ * centering_multiplier), gY); - } - if (gY < 0) { - gY += std::min((centering_speed_ * centering_multiplier), -gY); - } - } - if (gX == 0 && gY == 0) { - centering_speed_ = 0.0125f; - start_centering_ = false; - disable_sway_ = false; - } - } - - // Camera hax - if (input_state.mouse.x_delta || input_state.mouse.y_delta) { - float camX = *player_cam_x; - float camY = *player_cam_y; - - if (!cvars::invert_x) - { - camX += (((float)input_state.mouse.x_delta) / 10.f) * - (float)cvars::sensitivity; - } - else - { - camX -= (((float)input_state.mouse.x_delta) / 10.f) * - (float)cvars::sensitivity; - } - - // Add 'sway' to gun - float gun_sway_x = ((((float)input_state.mouse.x_delta) / 16000.f) * - (float)cvars::sensitivity) * bounds; - float gun_sway_y = ((((float)input_state.mouse.y_delta) / 16000.f) * - (float)cvars::sensitivity) * bounds; - - float gun_sway_x_changed = gX + gun_sway_x; - float gun_sway_y_changed = gY + gun_sway_y; - - if (!cvars::invert_y) { - camY -= (((float)input_state.mouse.y_delta) / 10.f) * - (float)cvars::sensitivity; - } else { - camY += (((float)input_state.mouse.y_delta) / 10.f) * - (float)cvars::sensitivity; - gun_sway_y_changed = gY - gun_sway_y; - } - - *player_cam_x = camX; - *player_cam_y = camY; - - if (cvars::ge_gun_sway && !disable_sway_) { - // Bound the 'sway' movement to [0.2:-0.2] to make it look a bit - // better (but only if the sway would make it go further OOB) - if (gun_sway_x_changed > (0.2f * bounds) && gun_sway_x > 0) { - gun_sway_x_changed = gX; - } - if (gun_sway_x_changed < -(0.2f * bounds) && gun_sway_x < 0) { - gun_sway_x_changed = gX; - } - if (gun_sway_y_changed > (0.2f * bounds) && gun_sway_y > 0) { - gun_sway_y_changed = gY; - } - if (gun_sway_y_changed < -(0.2f * bounds) && gun_sway_y < 0) { - gun_sway_y_changed = gY; - } - - gX = gun_sway_x_changed; - gY = gun_sway_y_changed; - } - } else { - if (!start_centering_) { - start_centering_ = true; - centering_speed_ = 0.0125f; - } - } - - gX = std::min(gX, bounds); - gX = std::max(gX, -bounds); - gY = std::min(gY, bounds); - gY = std::max(gY, -bounds); - - *player_crosshair_x = (gX * crosshair_multiplier); - *player_crosshair_y = (gY * crosshair_multiplier); - *player_gun_x = gX; - *player_gun_y = gY; - } - - return true; -} - -// GE modifier reduces LS-movement, to allow for walk speed to be reduced -// (ie a 'walk' button) -bool GoldeneyeGame::ModifierKeyHandler(uint32_t user_index, - RawInputState& input_state, - X_INPUT_STATE* out_state) { - - float thumb_lx = (int16_t)out_state->gamepad.thumb_lx; - float thumb_ly = (int16_t)out_state->gamepad.thumb_ly; - - // Work out angle from the current stick values - float angle = atan2f(thumb_ly, thumb_lx); - - // Sticks get set to SHRT_MAX if key pressed, use half of that - float distance = (float)SHRT_MAX; - distance /= 2; - - out_state->gamepad.thumb_lx = (int16_t)(distance * cosf(angle)); - out_state->gamepad.thumb_ly = (int16_t)(distance * sinf(angle)); - - // Return true to signal that we've handled the modifier, so default modifier won't be used - return true; -} - -} // namespace winkey -} // namespace hid -} // namespace xe diff --git a/src/xenia/hid/winkey/hookables/goldeneye.h b/src/xenia/hid/winkey/hookables/goldeneye.h deleted file mode 100644 index afe22f0739..0000000000 --- a/src/xenia/hid/winkey/hookables/goldeneye.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - ****************************************************************************** - * 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. * - ****************************************************************************** - */ - -#ifndef XENIA_HID_WINKEY_GOLDENEYE_H_ -#define XENIA_HID_WINKEY_GOLDENEYE_H_ - -#include "xenia/hid/winkey/hookables/hookable_game.h" - -namespace xe { -namespace hid { -namespace winkey { - -class GoldeneyeGame : public HookableGame { - public: - enum class GameBuild { - Unknown = 0, - - GoldenEye_Nov2007_Release, // 2007-11-16, "August 2007" build is a hacked - GoldenEye_Nov2007_Team, // copy of it - GoldenEye_Nov2007_Debug, - - PerfectDark_Devkit_33, // 09.12.03.0033 - PerfectDark_Release_52, // 10.02.16.0052 - PerfectDark_Devkit_102, // 10.03.04.0102 - PerfectDark_Release_104, // 10.03.07.0104 - PerfectDark_Release_107, // 10.04.13.0107 - }; - - ~GoldeneyeGame() override; - - bool IsGameSupported(); - bool DoHooks(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state); - bool ModifierKeyHandler(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state); - - private: - GameBuild game_build_ = GameBuild::Unknown; - - uint32_t prev_aim_mode_ = 0; - uint32_t prev_game_pause_flag_ = -1; - uint32_t prev_game_control_disabled_ = -1; - - float centering_speed_ = 0.0125f; - bool start_centering_ = false; - bool disable_sway_ = false; // temporarily prevents sway being applied -}; - -} // namespace winkey -} // namespace hid -} // namespace xe - -#endif // XENIA_HID_WINKEY_GOLDENEYE_H_ diff --git a/src/xenia/hid/winkey/hookables/halo3.cc b/src/xenia/hid/winkey/hookables/halo3.cc deleted file mode 100644 index a2f244cc11..0000000000 --- a/src/xenia/hid/winkey/hookables/halo3.cc +++ /dev/null @@ -1,206 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/hid/winkey/hookables/halo3.h" - -#include "xenia/base/platform_win.h" -#include "xenia/hid/hid_flags.h" -#include "xenia/hid/input_system.h" -#include "xenia/xbox.h" -#include "xenia/kernel/util/shim_utils.h" -#include "xenia/cpu/processor.h" -#include "xenia/kernel/xthread.h" - -using namespace xe::kernel; - -DECLARE_double(sensitivity); -DECLARE_bool(invert_y); -DECLARE_bool(invert_x); - -const uint32_t kTitleIdHalo3 = 0x4D5307E6; -const uint32_t kTitleIdHalo3ODST = 0x4D530877; -const uint32_t kTitleIdHaloReach = 0x4D53085B; -const uint32_t kTitleIdHalo4 = 0x4D530919; - -namespace xe { -namespace hid { -namespace winkey { - -Halo3Game::~Halo3Game() = default; - -struct GameBuildAddrs { - const char* build_string; - uint32_t build_string_addr; - uint32_t input_globals_offset; // can be found near usage of "player control globals" string - uint32_t camera_x_offset; - uint32_t camera_y_offset; -}; - -std::map supported_builds{ - { - Halo3Game::GameBuild::Debug_08172, - {"08172.07.03.08.2240.delta__cache_debug", 0x820BA40C, 0x1A30, 0x1C, 0x20} - }, - { - Halo3Game::GameBuild::Play_08172, - {"08172.07.03.08.2240.delta__cache_play", 0x820A1108, 0x1928, 0x1C, 0x20} - }, - { - Halo3Game::GameBuild::Profile_08172, - {"08172.07.03.08.2240.delta__cache_profile", 0x8201979C, 0x12C, 0x1C, 0x20} - }, - { - Halo3Game::GameBuild::Release_08172, - {"08172.07.03.08.2240.delta", 0x8205D39C, 0xC4, 0x1C, 0x20} - }, - { - Halo3Game::GameBuild::Test_08172, - {"08172.07.03.08.2240.delta__cache_test", 0x820A8744, 0x1928, 0x1C, 0x20} - }, - { - Halo3Game::GameBuild::Release_699E0227_11855, - {"11855.07.08.20.2317.halo3_ship__cache_release", 0x8203ADE8, 0x78, 0x1C, - 0x20} - }, - { - Halo3Game::GameBuild::Release_699E0227_12070, - {"12070.08.09.05.2031.halo3_ship__cache_release", 0x8203B3E4, 0x78, 0x1C, - 0x20} - }, - { - Halo3Game::GameBuild::Release_152AB680_13895, - {"13895.09.04.27.2201.atlas_relea__cache_release", 0x82048E38, 0xA8, 0x8C, - 0x90} - }, - { - Halo3Game::GameBuild::Release_566C10D3_11860, - {"11860.10.07.24.0147.omaha_relea", 0x82048A54, 0x74, 0x94, 0x98} - }, - { - Halo3Game::GameBuild::Release_566C10D3_12065, - {"12065.11.08.24.1738.tu1actual", 0x82048BCC, 0x74, 0x94, 0x98} - }, - { - Halo3Game::GameBuild::Release_1C9D20BC_20810, - {"20810.12.09.22.1647.main", 0x82129D78, 0x64, 0x134, 0x138} - }, - { - Halo3Game::GameBuild::Release_1C9D20BC_21522, - {"21522.13.10.17.1936.main", 0x82137090, 0x64, 0x134, 0x138} - } - - // H4 TODO: - // - 20975.12.10.25.1337.main 82129FB8 TU1 v0.0.1.15 - // - 21122.12.11.21.0101.main 8212A2E8 TU2 v0.0.2.15 - // - 21165.12.12.12.0112.main 8212A2E8 TU3 v0.0.3.15 - // - 21339.13.02.05.0117.main 8212A890 TU4 v0.0.4.15 - // - 21391.13.03.13.1711.main 821365D0 TU5 v0.0.5.15 - // - 21401.13.04.23.1849.main 82136788 TU6 v0.0.6.15 - // - 21501.13.08.06.2311.main ? (mentioned in TU8 xex) -}; - -bool Halo3Game::IsGameSupported() { - auto title_id = kernel_state()->title_id(); - - if (title_id != kTitleIdHalo3 && title_id != kTitleIdHalo3ODST && - title_id != kTitleIdHaloReach && title_id != kTitleIdHalo4) { - return false; - } - - for (auto& build : supported_builds) { - auto* build_ptr = kernel_memory()->TranslateVirtual( - build.second.build_string_addr); - - if (strcmp(build_ptr, build.second.build_string) == 0) { - game_build_ = build.first; - return true; - } - } - - return false; -} - -#define IS_KEY_DOWN(x) (input_state.key_states[x]) - -bool Halo3Game::DoHooks(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state) { - if (!IsGameSupported()) { - return false; - } - - if (supported_builds.count(game_build_)) { - // HACKHACK: Doesn't seem to be any way to get tls_static_address_ besides - // this (XThread::GetTLSValue only returns tls_dynamic_address_, and doesn't - // seem to be any functions to get static_addr...) - - xe::kernel::XThread* current_thread = xe::kernel::XThread::GetCurrentThread(); - - if (!current_thread) { - return false; - } - - uint32_t pcr_addr = static_cast( - current_thread->thread_state()->context()->r[13]); - - auto tls_addr = - kernel_memory()->TranslateVirtual(pcr_addr)->tls_ptr; - - auto global_addr = *kernel_memory()->TranslateVirtual*>( - tls_addr + supported_builds[game_build_].input_globals_offset); - - if (global_addr) { - auto* input_globals = kernel_memory()->TranslateVirtual(global_addr); - - auto* player_cam_x = reinterpret_cast*>( - input_globals + supported_builds[game_build_].camera_x_offset); - auto* player_cam_y = reinterpret_cast*>( - input_globals + supported_builds[game_build_].camera_y_offset); - - // Have to do weird things converting it to normal float otherwise - // xe::be += treats things as int? - float camX = (float)*player_cam_x; - float camY = (float)*player_cam_y; - - if (!cvars::invert_x) - { - camX -= (((float)input_state.mouse.x_delta) / 1000.f) * - (float)cvars::sensitivity; - } - else - { - camX += (((float)input_state.mouse.x_delta) / 1000.f) * - (float)cvars::sensitivity; - } - - if (!cvars::invert_y) { - camY -= (((float)input_state.mouse.y_delta) / 1000.f) * - (float)cvars::sensitivity; - } else { - camY += (((float)input_state.mouse.y_delta) / 1000.f) * - (float)cvars::sensitivity; - } - - *player_cam_x = camX; - *player_cam_y = camY; - } - } - - return true; -} - -bool Halo3Game::ModifierKeyHandler(uint32_t user_index, - RawInputState& input_state, - X_INPUT_STATE* out_state) { - // Defer to default modifier (swaps LS movement over to RS) - return false; -} - -} // namespace winkey -} // namespace hid -} // namespace xe diff --git a/src/xenia/hid/winkey/hookables/halo3.h b/src/xenia/hid/winkey/hookables/halo3.h deleted file mode 100644 index 6863a604dd..0000000000 --- a/src/xenia/hid/winkey/hookables/halo3.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - ****************************************************************************** - * 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. * - ****************************************************************************** - */ - -#ifndef XENIA_HID_WINKEY_HALO3_H_ -#define XENIA_HID_WINKEY_HALO3_H_ - -#include "xenia/hid/winkey/hookables/hookable_game.h" - -namespace xe { -namespace hid { -namespace winkey { - -class Halo3Game : public HookableGame { - public: - enum class GameBuild { - Unknown, - Debug_08172, // Mar 8 2007 (08172.07.03.08.2240.delta__cache_debug) - Play_08172, // Mar 8 2007 (08172.07.03.08.2240.delta__cache_play) - Profile_08172, // Mar 8 2007 (08172.07.03.08.2240.delta__cache_profile) - Release_08172, // Mar 8 2007 (08172.07.03.08.2240.delta) - Test_08172, // Mar 8 2007 (08172.07.03.08.2240.delta__cache_test) - Release_699E0227_11855, // Aug 20 2007, TU0, media ID 699E0227, v0.0.0.42 - // (11855.07.08.20.2317.halo3_ship__cache_release) - Release_699E0227_12070, // Sep 5 2008, TU3, media ID 699E0227, v0.0.3.42 - // (12070.08.09.05.2031.halo3_ship__cache_release) - - // Halo 3: ODST - Release_152AB680_13895, // Apr 27 2009, TU0, media ID 152AB680, v0.0.0.11 - // (13895.09.04.27.2201.atlas_relea__cache_release) - - // Halo: Reach - Release_566C10D3_11860, // Jul 24 2010, TU0, media ID 566C10D3, v0.0.0.1 - // (11860.10.07.24.0147.omaha_relea) - Release_566C10D3_12065, // Aug 24 2011, TU1, media ID 566C10D3, v0.0.1.1 - // (12065.11.08.24.1738.tu1actual) - - // Halo 4 - Release_1C9D20BC_20810, // Sep 22 2012, TU0, media ID 1C9D20BC, v0.0.0.15 - // (20810.12.09.22.1647.main) - Release_1C9D20BC_21522, // Oct 17 2013, TU8/TU10? media ID 1C9D20BC - // v0.0.10.15 (21522.13.10.17.1936.main) - }; - - ~Halo3Game() override; - - bool IsGameSupported(); - bool DoHooks(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state); - bool ModifierKeyHandler(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state); - - private: - GameBuild game_build_ = GameBuild::Unknown; -}; - -} // namespace winkey -} // namespace hid -} // namespace xe - -#endif // XENIA_HID_WINKEY_HALO3_H_ diff --git a/src/xenia/hid/winkey/hookables/hookable_game.h b/src/xenia/hid/winkey/hookables/hookable_game.h deleted file mode 100644 index 5b90046035..0000000000 --- a/src/xenia/hid/winkey/hookables/hookable_game.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - ****************************************************************************** - * 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. * - ****************************************************************************** - */ - -#ifndef XENIA_HID_WINKEY_HOOKABLE_GAME_H_ -#define XENIA_HID_WINKEY_HOOKABLE_GAME_H_ - -#include "xenia/xbox.h" -#include "xenia/hid/input.h" - -namespace xe { -namespace hid { -namespace winkey { - -struct MouseEvent { - int32_t x_delta = 0; - int32_t y_delta = 0; - int32_t buttons = 0; - int32_t wheel_delta = 0; -}; - -struct RawInputState { - MouseEvent mouse; - bool* key_states; -}; - -class HookableGame { - public: - virtual ~HookableGame() = default; - - virtual bool IsGameSupported() = 0; - virtual bool DoHooks(uint32_t user_index, RawInputState& input_state, - X_INPUT_STATE* out_state) = 0; - virtual bool ModifierKeyHandler(uint32_t user_index, - RawInputState& input_state, - X_INPUT_STATE* out_state) = 0; -}; - -} // namespace winkey -} // namespace hid -} // namespace xe - -#endif // XENIA_HID_WINKEY_HOOKABLE_GAME_H_ diff --git a/src/xenia/hid/winkey/premake5.lua b/src/xenia/hid/winkey/premake5.lua index 5f85b7f240..0e3b865808 100644 --- a/src/xenia/hid/winkey/premake5.lua +++ b/src/xenia/hid/winkey/premake5.lua @@ -10,8 +10,7 @@ project("xenia-hid-winkey") "xenia-base", "xenia-hid", "xenia-ui", - "xenia-kernel" }) defines({ }) - recursive_platform_files() + local_platform_files() diff --git a/src/xenia/hid/winkey/winkey_input_driver.cc b/src/xenia/hid/winkey/winkey_input_driver.cc index 2e10132ecc..2f4d7a21ad 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.cc +++ b/src/xenia/hid/winkey/winkey_input_driver.cc @@ -14,217 +14,7 @@ #include "xenia/hid/hid_flags.h" #include "xenia/hid/input_system.h" #include "xenia/ui/virtual_key.h" -#include "xenia/kernel/util/shim_utils.h" #include "xenia/ui/window.h" -#include "xenia/ui/window_win.h" -#include "xenia/base/system.h" - -#include "xenia/kernel/kernel_state.h" - -#include "xenia/hid/winkey/hookables/goldeneye.h" -#include "xenia/hid/winkey/hookables/halo3.h" -#include "xenia/hid/winkey/hookables/SourceEngine.h" -#include "xenia/hid/winkey/hookables/Crackdown2.h" - -DEFINE_bool(invert_y, false, "Invert mouse Y axis", "MouseHook"); -DEFINE_bool(invert_x, false, "Invert mouse X axis", "MouseHook"); -DEFINE_bool(swap_wheel, false, - "Swaps binds for wheel, so wheel up will go to next weapon & down " - "will go to prev", - "MouseHook"); -DEFINE_double(sensitivity, 1, "Mouse sensitivity", "MouseHook"); -DEFINE_bool(disable_autoaim, true, - "Disable autoaim in games that support it (currently GE & PD)", - "MouseHook"); -DEFINE_double(source_sniper_sensitivity, 0, "Source Sniper Sensitivity", - "MouseHook"); -DEFINE_int32(walk_orthogonal, 22800, "Joystick movement for forward/backward/left/right shiftwalking, default 22800 equates to 134.99 h.u./s", "MouseHook"); -DEFINE_int32(walk_diagonal, 18421, "Joystick movement for diagonal shiftwalking, default 18421 equates to 134.99 h.u./s", "MouseHook"); - -const uint32_t kTitleIdDefaultBindings = 0; - -static const std::unordered_map kXInputButtons = { - {"up", 0x1}, - {"down", 0x2}, - {"left", 0x4}, - {"right", 0x8}, - - {"start", 0x10}, - {"back", 0x20}, - - {"ls", 0x40}, - {"rs", 0x80}, - - {"lb", 0x100}, - {"rb", 0x200}, - - {"a", 0x1000}, - {"b", 0x2000}, - {"x", 0x4000}, - {"y", 0x8000}, - - {"lt", XINPUT_BIND_LEFT_TRIGGER}, - {"rt", XINPUT_BIND_RIGHT_TRIGGER}, - - {"ls-up", XINPUT_BIND_LS_UP}, - {"ls-down", XINPUT_BIND_LS_DOWN}, - {"ls-left", XINPUT_BIND_LS_LEFT}, - {"ls-right", XINPUT_BIND_LS_RIGHT}, - - {"rs-up", XINPUT_BIND_RS_UP}, - {"rs-down", XINPUT_BIND_RS_DOWN}, - {"rs-left", XINPUT_BIND_RS_LEFT}, - {"rs-right", XINPUT_BIND_RS_RIGHT}, - - {"modifier", XINPUT_BIND_MODIFIER}}; - -static const std::unordered_map kKeyMap = { - {"lclick", VK_LBUTTON}, - {"lmouse", VK_LBUTTON}, - {"mouse1", VK_LBUTTON}, - {"rclick", VK_RBUTTON}, - {"rmouse", VK_RBUTTON}, - {"mouse2", VK_RBUTTON}, - {"mclick", VK_MBUTTON}, - {"mmouse", VK_MBUTTON}, - {"mouse3", VK_MBUTTON}, - {"mouse4", VK_XBUTTON1}, - {"mouse5", VK_XBUTTON2}, - {"mwheelup", VK_BIND_MWHEELUP}, - {"mwheeldown", VK_BIND_MWHEELDOWN}, - - {"control", VK_LCONTROL}, - {"ctrl", VK_LCONTROL}, - {"alt", VK_LMENU}, - {"lcontrol", VK_LCONTROL}, - {"lctrl", VK_LCONTROL}, - {"lalt", VK_LMENU}, - {"rcontrol", VK_RCONTROL}, - {"rctrl", VK_RCONTROL}, - {"altgr", VK_RMENU}, - {"ralt", VK_RMENU}, - - {"lshift", VK_LSHIFT}, - {"shift", VK_LSHIFT}, - {"rshift", VK_RSHIFT}, - - {"backspace", VK_BACK}, - {"down", VK_DOWN}, - {"left", VK_LEFT}, - {"right", VK_RIGHT}, - {"up", VK_UP}, - {"delete", VK_DELETE}, - {"end", VK_END}, - {"escape", VK_ESCAPE}, - {"home", VK_HOME}, - {"pgdown", VK_NEXT}, - {"pgup", VK_PRIOR}, - {"return", VK_RETURN}, - {"enter", VK_RETURN}, - {"renter", VK_SEPARATOR}, - {"space", VK_SPACE}, - {"tab", VK_TAB}, - {"f1", VK_F1}, - {"f2", VK_F2}, - {"f3", VK_F3}, - {"f4", VK_F4}, - {"f5", VK_F5}, - {"f6", VK_F6}, - {"f7", VK_F7}, - {"f8", VK_F8}, - {"f9", VK_F9}, - {"f10", VK_F10}, - {"f11", VK_F11}, - {"f12", VK_F12}, - {"f13", VK_F13}, - {"f14", VK_F14}, - {"f15", VK_F15}, - {"f16", VK_F16}, - {"f17", VK_F17}, - {"f18", VK_F18}, - {"f19", VK_F19}, - {"f20", VK_F20}, - {"num0", VK_NUMPAD0}, - {"num1", VK_NUMPAD1}, - {"num2", VK_NUMPAD2}, - {"num3", VK_NUMPAD3}, - {"num4", VK_NUMPAD4}, - {"num5", VK_NUMPAD5}, - {"num6", VK_NUMPAD6}, - {"num7", VK_NUMPAD7}, - {"num8", VK_NUMPAD8}, - {"num9", VK_NUMPAD9}, - {"num+", VK_ADD}, - {"num-", VK_SUBTRACT}, - {"num*", VK_MULTIPLY}, - {"num/", VK_DIVIDE}, - {"num.", VK_DECIMAL}, - {"numenter", VK_SEPARATOR}, - {";", VK_OEM_1}, - {":", VK_OEM_1}, - {"=", VK_OEM_PLUS}, - {"+", VK_OEM_PLUS}, - {",", VK_OEM_COMMA}, - {"<", VK_OEM_COMMA}, - {"-", VK_OEM_MINUS}, - {"_", VK_OEM_MINUS}, - {".", VK_OEM_PERIOD}, - {">", VK_OEM_PERIOD}, - {"/", VK_OEM_2}, - {"?", VK_OEM_2}, - {"'", VK_OEM_3}, // uk keyboard - {"@", VK_OEM_3}, // uk keyboard - {"[", VK_OEM_4}, - {"{", VK_OEM_4}, - {"\\", VK_OEM_5}, - {"|", VK_OEM_5}, - {"]", VK_OEM_6}, - {"}", VK_OEM_6}, - {"#", VK_OEM_7}, // uk keyboard - {"\"", VK_OEM_7}, - {"`", VK_OEM_8}, // uk keyboard, no idea what this is on US.. -}; - -const std::string WHITESPACE = " \n\r\t\f\v"; - -std::string ltrim(const std::string& s) { - size_t start = s.find_first_not_of(WHITESPACE); - return (start == std::string::npos) ? "" : s.substr(start); -} - -std::string rtrim(const std::string& s) { - size_t end = s.find_last_not_of(WHITESPACE); - return (end == std::string::npos) ? "" : s.substr(0, end + 1); -} - -std::string trim(const std::string& s) { return rtrim(ltrim(s)); } - -int ParseButtonCombination(const char* combo) { - size_t len = strlen(combo); - - int retval = 0; - std::string cur_token; - - // Parse combo tokens into buttons bitfield (tokens seperated by any - // non-alphabetical char, eg. +) - for (size_t i = 0; i < len; i++) { - char c = combo[i]; - - if (!isalpha(c) && c != '-') { - if (cur_token.length() && kXInputButtons.count(cur_token)) - retval |= kXInputButtons.at(cur_token); - - cur_token.clear(); - continue; - } - cur_token += ::tolower(c); - } - - if (cur_token.length() && kXInputButtons.count(cur_token)) - retval |= kXInputButtons.at(cur_token); - - return retval; -} #define XE_HID_WINKEY_BINDING(button, description, cvar_name, \ cvar_default_value) \ @@ -249,6 +39,7 @@ DEFINE_int32(keyboard_passthru_user_index, -1, namespace xe { namespace hid { namespace winkey { +using namespace xe::string_util; bool static IsPassThruForUserEnabled(uint32_t user_index) { if (cvars::keyboard_passthru_user_index == -1) { @@ -269,6 +60,137 @@ bool __inline IsKeyDown(ui::VirtualKey virtual_key) { return IsKeyDown(static_cast(virtual_key)); } +// Lookup the value of xinput string +static const std::map kXInputButtons = { + {"up", ui::VirtualKey::kXInputPadDpadUp}, + {"down", ui::VirtualKey::kXInputPadDpadDown}, + {"left", ui::VirtualKey::kXInputPadDpadLeft}, + {"right", ui::VirtualKey::kXInputPadDpadRight}, + + {"start", ui::VirtualKey::kXInputPadStart}, + {"back", ui::VirtualKey::kXInputPadBack}, + {"guide", ui::VirtualKey::kXInputPadGuide}, + + {"ls", ui::VirtualKey::kXInputPadLThumbPress}, + {"rs", ui::VirtualKey::kXInputPadRThumbPress}, + + {"lb", ui::VirtualKey::kXInputPadLShoulder}, + {"rb", ui::VirtualKey::kXInputPadRShoulder}, + + {"a", ui::VirtualKey::kXInputPadA}, + {"b", ui::VirtualKey::kXInputPadB}, + {"x", ui::VirtualKey::kXInputPadX}, + {"y", ui::VirtualKey::kXInputPadY}, + + {"lt", ui::VirtualKey::kXInputPadLTrigger}, + {"rt", ui::VirtualKey::kXInputPadRTrigger}, + + {"ls-up", ui::VirtualKey::kXInputPadLThumbUp}, + {"ls-down", ui::VirtualKey::kXInputPadLThumbDown}, + {"ls-left", ui::VirtualKey::kXInputPadLThumbLeft}, + {"ls-right", ui::VirtualKey::kXInputPadLThumbRight}, + + {"rs-up", ui::VirtualKey::kXInputPadRThumbUp}, + {"rs-down", ui::VirtualKey::kXInputPadRThumbDown}, + {"rs-left", ui::VirtualKey::kXInputPadRThumbLeft}, + {"rs-right", ui::VirtualKey::kXInputPadRThumbRight}, + + {"modifier", ui::VirtualKey::kModifier}}; + +// Lookup the value of key string +static const std::map kKeyMap = { + {"control", ui::VirtualKey::kLControl}, + {"ctrl", ui::VirtualKey::kLControl}, + {"alt", ui::VirtualKey::kLMenu}, + {"lcontrol", ui::VirtualKey::kLControl}, + {"lctrl", ui::VirtualKey::kLControl}, + {"lalt", ui::VirtualKey::kLMenu}, + {"rcontrol", ui::VirtualKey::kRControl}, + {"rctrl", ui::VirtualKey::kRControl}, + {"altgr", ui::VirtualKey::kRMenu}, + {"ralt", ui::VirtualKey::kRMenu}, + + {"lshift", ui::VirtualKey::kLShift}, + {"shift", ui::VirtualKey::kLShift}, + {"rshift", ui::VirtualKey::kRShift}, + + {"backspace", ui::VirtualKey::kBack}, + {"down", ui::VirtualKey::kDown}, + {"left", ui::VirtualKey::kLeft}, + {"right", ui::VirtualKey::kRight}, + {"up", ui::VirtualKey::kUp}, + {"delete", ui::VirtualKey::kDelete}, + {"end", ui::VirtualKey::kEnd}, + {"escape", ui::VirtualKey::kEscape}, + {"home", ui::VirtualKey::kHome}, + {"pgdown", ui::VirtualKey::kNext}, + {"pgup", ui::VirtualKey::kPrior}, + {"return", ui::VirtualKey::kReturn}, + {"enter", ui::VirtualKey::kReturn}, + {"renter", ui::VirtualKey::kSeparator}, + {"space", ui::VirtualKey::kSpace}, + {"tab", ui::VirtualKey::kTab}, + {"f1", ui::VirtualKey::kF1}, + {"f2", ui::VirtualKey::kF2}, + {"f3", ui::VirtualKey::kF3}, + {"f4", ui::VirtualKey::kF4}, + {"f5", ui::VirtualKey::kF5}, + {"f6", ui::VirtualKey::kF6}, + {"f7", ui::VirtualKey::kF7}, + {"f8", ui::VirtualKey::kF8}, + {"f9", ui::VirtualKey::kF9}, + {"f10", ui::VirtualKey::kF10}, + {"f11", ui::VirtualKey::kF11}, + {"f12", ui::VirtualKey::kF12}, + {"f13", ui::VirtualKey::kF13}, + {"f14", ui::VirtualKey::kF14}, + {"f15", ui::VirtualKey::kF15}, + {"f16", ui::VirtualKey::kF16}, + {"f17", ui::VirtualKey::kF17}, + {"f18", ui::VirtualKey::kF18}, + {"f19", ui::VirtualKey::kF19}, + {"f20", ui::VirtualKey::kF10}, + {"num0", ui::VirtualKey::kNumpad0}, + {"num1", ui::VirtualKey::kNumpad1}, + {"num2", ui::VirtualKey::kNumpad2}, + {"num3", ui::VirtualKey::kNumpad3}, + {"num4", ui::VirtualKey::kNumpad4}, + {"num5", ui::VirtualKey::kNumpad5}, + {"num6", ui::VirtualKey::kNumpad6}, + {"num7", ui::VirtualKey::kNumpad7}, + {"num8", ui::VirtualKey::kNumpad8}, + {"num9", ui::VirtualKey::kNumpad9}, + {"num+", ui::VirtualKey::kAdd}, + {"num-", ui::VirtualKey::kSubtract}, + {"num*", ui::VirtualKey::kMultiply}, + {"num/", ui::VirtualKey::kDivide}, + {"num.", ui::VirtualKey::kDecimal}, + {"numenter", ui::VirtualKey::kSeparator}, + {";", ui::VirtualKey::kOem1}, + {":", ui::VirtualKey::kOem1}, + {"=", ui::VirtualKey::kOemPlus}, + {"+", ui::VirtualKey::kOemPlus}, + {",", ui::VirtualKey::kOemComma}, + {"<", ui::VirtualKey::kOemComma}, + {"-", ui::VirtualKey::kOemMinus}, + {"_", ui::VirtualKey::kOemMinus}, + {".", ui::VirtualKey::kOemPeriod}, + {">", ui::VirtualKey::kOemPeriod}, + {"/", ui::VirtualKey::kOem2}, + {"?", ui::VirtualKey::kOem2}, + {"'", ui::VirtualKey::kOem3}, // uk keyboard + {"@", ui::VirtualKey::kOem3}, // uk keyboard + {"[", ui::VirtualKey::kOem4}, + {"{", ui::VirtualKey::kOem4}, + {"\\", ui::VirtualKey::kOem5}, + {"|", ui::VirtualKey::kOem5}, + {"]", ui::VirtualKey::kOem6}, + {"}", ui::VirtualKey::kOem6}, + {"#", ui::VirtualKey::kOem7}, // uk keyboard + {"\"", ui::VirtualKey::kOem7}, + {"`", ui::VirtualKey::kOem8}, // uk keyboard, no idea what this is on US.. +}; + void WinKeyInputDriver::ParseKeyBinding(ui::VirtualKey output_key, const std::string_view description, const std::string_view source_tokens) { @@ -309,188 +231,129 @@ void WinKeyInputDriver::ParseKeyBinding(ui::VirtualKey output_key, } } -WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window, - size_t window_z_order) - : InputDriver(window, window_z_order), window_input_listener_(*this) { -#define XE_HID_WINKEY_BINDING(button, description, cvar_name, \ - cvar_default_value) \ - ParseKeyBinding(xe::ui::VirtualKey::kXInputPad##button, description, \ - cvars::cvar_name); -#include "winkey_binding_table.inc" -#undef XE_HID_WINKEY_BINDING +ui::VirtualKey WinKeyInputDriver::ParseButtonCombination(const char* combo) { + size_t len = strlen(combo); + + uint16_t retval = 0; + std::string cur_token; - memset(key_states_, 0, 256); + // Parse combo tokens into buttons bitfield (tokens separated by any + // non-alphabetical char, eg. +) + for (size_t i = 0; i < len; i++) { + char c = combo[i]; - // Register our supported hookable games - hookable_games_.push_back(std::move(std::make_unique())); - hookable_games_.push_back(std::move(std::make_unique())); - hookable_games_.push_back(std::move(std::make_unique())); - hookable_games_.push_back(std::move(std::make_unique())); + if (!isalpha(c) && c != '-') { + if (cur_token.length() && kXInputButtons.count(cur_token)) + retval |= static_cast(kXInputButtons.at(cur_token)); + + cur_token.clear(); + continue; + } + cur_token += ::tolower(c); + } + + if (cur_token.length() && kXInputButtons.count(cur_token)) + retval |= static_cast(kXInputButtons.at(cur_token)); + + return static_cast(retval); +} + +void WinKeyInputDriver::ParseCustomKeyBinding( + const std::string_view bindings_file) { + if (!std::filesystem::exists(bindings_file)) { + return; + } // Read bindings file if it exists - std::ifstream binds("bindings.ini"); - if (!binds.is_open()) { - xe::ShowSimpleMessageBox( - xe::SimpleMessageBoxType::Warning, - "Xenia failed to load bindings.ini file, MouseHook won't have any keys bound!"); - } else { - std::string cur_section = "default"; - uint32_t cur_game = kTitleIdDefaultBindings; - std::unordered_map cur_binds; - - std::string line; - while (std::getline(binds, line)) { - line = trim(line); - if (!line.length()) { - continue; // blank line - } - if (line[0] == ';') { - continue; // comment - } + std::ifstream binds(bindings_file.data()); - if (line.length() >= 3 && line[0] == '[' && - line[line.length() - 1] == ']') { + std::string cur_section = "default"; + uint32_t title_id = 0; - // New section - if (cur_binds.size() > 0) { - key_binds_.emplace(cur_game, cur_binds); - cur_binds.clear(); - } - cur_section = line.substr(1, line.length() - 2); - auto sep = cur_section.find_first_of(' '); - if (sep >= 0) { - cur_section = cur_section.substr(0, sep); - } - cur_game = std::stoul(cur_section, nullptr, 16); + std::map cur_binds; - continue; - } + std::string line; + while (std::getline(binds, line)) { + line = trim(line); + if (!line.length()) { + continue; // blank line + } + if (line[0] == ';') { + continue; // comment + } - // Not a section, must be bind - auto sep = line.find_last_of('='); - if (sep < 0) { - continue; // invalid + if (line.length() >= 3 && line[0] == '[' && + line[line.length() - 1] == ']') { + // New section + if (cur_binds.size() > 0) { + key_binds_.emplace(title_id, cur_binds); + cur_binds.clear(); } - auto key_str = trim(line.substr(0, sep)); - auto val_str = trim(line.substr(sep + 1)); - - // key tolower - std::transform(key_str.begin(), key_str.end(), key_str.begin(), - [](unsigned char c) { return std::tolower(c); }); - - // Parse key - uint32_t key = 0; - if (kKeyMap.count(key_str)) { - key = kKeyMap.at(key_str); - } else { - if (key_str.length() == 1 && - (isalpha(key_str[0]) || isdigit(key_str[0]))) { - key = (unsigned char)toupper(key_str[0]); - } + cur_section = line.substr(1, line.length() - 2); + auto sep = cur_section.find_first_of(' '); + if (sep >= 0) { + cur_section = cur_section.substr(0, sep); } - if (!key) { - continue; // unknown key - } + title_id = std::stoul(cur_section, nullptr, 16); - // Parse value - uint32_t value = ParseButtonCombination(val_str.c_str()); - cur_binds.emplace(key, value); - } - if (cur_binds.size() > 0) { - key_binds_.emplace(cur_game, cur_binds); - cur_binds.clear(); + continue; } - } - // Register our event listeners - window->on_raw_mouse.AddListener([this](ui::MouseEvent& evt) { - if (!is_active()) { - return; + // Not a section, must be bind + auto sep = line.find_last_of('='); + if (sep < 0) { + continue; // invalid } - std::unique_lock mouse_lock(mouse_mutex_); + auto key_str = trim(line.substr(0, sep)); + auto val_str = trim(line.substr(sep + 1)); - MouseEvent mouse; - mouse.x_delta = evt.x(); - mouse.y_delta = evt.y(); - mouse.buttons = evt.scroll_x(); - mouse.wheel_delta = evt.scroll_y(); - mouse_events_.push(mouse); + // key tolower + std::transform(key_str.begin(), key_str.end(), key_str.begin(), + [](unsigned char c) { return std::tolower(c); }); - { - std::unique_lock key_lock(key_mutex_); - if (mouse.buttons & RI_MOUSE_LEFT_BUTTON_DOWN) { - key_states_[VK_LBUTTON] = true; - } - if (mouse.buttons & RI_MOUSE_LEFT_BUTTON_UP) { - key_states_[VK_LBUTTON] = false; - } - if (mouse.buttons & RI_MOUSE_RIGHT_BUTTON_DOWN) { - key_states_[VK_RBUTTON] = true; - } - if (mouse.buttons & RI_MOUSE_RIGHT_BUTTON_UP) { - key_states_[VK_RBUTTON] = false; - } - if (mouse.buttons & RI_MOUSE_MIDDLE_BUTTON_DOWN) { - key_states_[VK_MBUTTON] = true; - } - if (mouse.buttons & RI_MOUSE_MIDDLE_BUTTON_UP) { - key_states_[VK_MBUTTON] = false; - } - if (mouse.buttons & RI_MOUSE_BUTTON_4_DOWN) { - key_states_[VK_XBUTTON1] = true; - } - if (mouse.buttons & RI_MOUSE_BUTTON_4_UP) { - key_states_[VK_XBUTTON1] = false; - } - if (mouse.buttons & RI_MOUSE_BUTTON_5_DOWN) { - key_states_[VK_XBUTTON2] = true; - } - if (mouse.buttons & RI_MOUSE_BUTTON_5_UP) { - key_states_[VK_XBUTTON2] = false; - } + // Parse key + ui::VirtualKey key = ui::VirtualKey::kNone; + + if (kKeyMap.count(key_str)) { + key = kKeyMap.at(key_str); + } else if (key_str.length() == 1 && + (isalpha(key_str[0]) || isdigit(key_str[0]))) { + key = static_cast(toupper(key_str[0])); } - }); - window->on_raw_keyboard.AddListener([this, window](ui::KeyEvent& evt) { - if (!is_active()) { - return; + if (key == ui::VirtualKey::kNone) { + continue; // unknown key } - std::unique_lock key_lock(key_mutex_); - key_states_[(uint16_t)evt.virtual_key() & 0xFF] = evt.prev_state(); - }); - - window->AddInputListener(&window_input_listener_, window_z_order); + // Parse value + auto const value = ParseButtonCombination(val_str.c_str()); + cur_binds.emplace(key, value); + } - window->on_key_down.AddListener([this](ui::KeyEvent& evt) { - if (!is_active()) { - return; - } - auto global_lock = global_critical_region_.Acquire(); + if (cur_binds.size() > 0) { + key_binds_.emplace(title_id, cur_binds); + cur_binds.clear(); + } +} - KeyEvent key; - key.virtual_key = evt.virtual_key(); - key.transition = true; - key.prev_state = evt.prev_state(); - key.repeat_count = evt.repeat_count(); - key_events_.push(key); - }); - window->on_key_up.AddListener([this](ui::KeyEvent& evt) { - if (!is_active()) { - return; - } - auto global_lock = global_critical_region_.Acquire(); +WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window, + size_t window_z_order) + : InputDriver(window, window_z_order), window_input_listener_(*this) { +#define XE_HID_WINKEY_BINDING(button, description, cvar_name, \ + cvar_default_value) \ + ParseKeyBinding(xe::ui::VirtualKey::kXInputPad##button, description, \ + cvars::cvar_name); +#include "winkey_binding_table.inc" +#undef XE_HID_WINKEY_BINDING + + auto path = std::filesystem::current_path() / "bindings.ini"; + + ParseCustomKeyBinding(path.string()); - KeyEvent key; - key.virtual_key = evt.virtual_key(); - key.transition = false; - key.prev_state = evt.prev_state(); - key.repeat_count = evt.repeat_count(); - key_events_.push(key); - }); + window->AddInputListener(&window_input_listener_, window_z_order); } WinKeyInputDriver::~WinKeyInputDriver() { @@ -521,9 +384,6 @@ X_RESULT WinKeyInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags, return X_ERROR_SUCCESS; } -#define IS_KEY_TOGGLED(key) ((GetKeyState(key) & 0x1) == 0x1) -#define IS_KEY_DOWN(key) ((GetAsyncKeyState(key) & 0x8000) == 0x8000) - X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, X_INPUT_STATE* out_state) { if (!IsPassThruForUserEnabled(user_index) && @@ -544,102 +404,102 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, X_RESULT result = X_ERROR_SUCCESS; - RawInputState state; - - if (window()->HasFocus() && is_active() && xe::kernel::kernel_state()->has_executable_module()) { - { - std::unique_lock mouse_lock(mouse_mutex_); - while (!mouse_events_.empty()) { - auto& mouse = mouse_events_.front(); - state.mouse.x_delta += mouse.x_delta; - state.mouse.y_delta += mouse.y_delta; - state.mouse.wheel_delta += mouse.wheel_delta; - mouse_events_.pop(); - } - } + if (window()->HasFocus() && is_active()) { + for (int i = 0; i < sizeof(key_states_); i++) { + if (key_states_[i]) { + const auto& binds = key_binds_.at(title_id); + const auto vk_key = static_cast(i); - if (state.mouse.wheel_delta != 0) { - if (cvars::swap_wheel) { - state.mouse.wheel_delta = -state.mouse.wheel_delta; + if (!binds.count(vk_key)) { + break; } - } - { - std::unique_lock key_lock(key_mutex_); - state.key_states = key_states_; + const auto key_binding = binds.at(vk_key); - // Handle key bindings - uint32_t cur_game = xe::kernel::kernel_state()->title_id(); - if (!key_binds_.count(cur_game)) { - cur_game = kTitleIdDefaultBindings; - } - if (key_binds_.count(cur_game)) { - auto& binds = key_binds_.at(cur_game); - auto process_binding = [binds, &buttons, &left_trigger, - &right_trigger, &thumb_lx, &thumb_ly, - &thumb_rx, &thumb_ry, - &modifier_pressed](uint32_t key) { - if (!binds.count(key)) { - return; - } - auto binding = binds.at(key); - buttons |= (binding & XINPUT_BUTTONS_MASK); - - if (binding & XINPUT_BIND_LEFT_TRIGGER) { - left_trigger = 0xFF; - } - - if (binding & XINPUT_BIND_RIGHT_TRIGGER) { - right_trigger = 0xFF; - } - - if (binding & XINPUT_BIND_LS_UP) { - thumb_ly = SHRT_MAX; - } - if (binding & XINPUT_BIND_LS_DOWN) { - thumb_ly = SHRT_MIN; - } - if (binding & XINPUT_BIND_LS_LEFT) { - thumb_lx = SHRT_MIN; - } - if (binding & XINPUT_BIND_LS_RIGHT) { - thumb_lx = SHRT_MAX; - } - - if (binding & XINPUT_BIND_RS_UP) { - thumb_ry = SHRT_MAX; - } - if (binding & XINPUT_BIND_RS_DOWN) { - thumb_ry = SHRT_MIN; - } - if (binding & XINPUT_BIND_RS_LEFT) { - thumb_rx = SHRT_MIN; - } - if (binding & XINPUT_BIND_RS_RIGHT) { - thumb_rx = SHRT_MAX; - } - - if (binding & XINPUT_BIND_MODIFIER) { - modifier_pressed = true; - } - }; - - if (state.mouse.wheel_delta != 0) { - if (state.mouse.wheel_delta > 0) { - process_binding(VK_BIND_MWHEELUP); - } else { - process_binding(VK_BIND_MWHEELDOWN); - } - } - - for (int i = 0; i < 0x100; i++) { - if (key_states_[i]) { - process_binding(i); - } - } + // use if instead for binding combinations? + switch (key_binding) { + case ui::VirtualKey::kXInputPadA: + buttons |= X_INPUT_GAMEPAD_A; + break; + case ui::VirtualKey::kXInputPadY: + buttons |= X_INPUT_GAMEPAD_Y; + break; + case ui::VirtualKey::kXInputPadB: + buttons |= X_INPUT_GAMEPAD_B; + break; + case ui::VirtualKey::kXInputPadX: + buttons |= X_INPUT_GAMEPAD_X; + break; + case ui::VirtualKey::kXInputPadGuide: + buttons |= X_INPUT_GAMEPAD_GUIDE; + break; + case ui::VirtualKey::kXInputPadDpadLeft: + buttons |= X_INPUT_GAMEPAD_DPAD_LEFT; + break; + case ui::VirtualKey::kXInputPadDpadRight: + buttons |= X_INPUT_GAMEPAD_DPAD_RIGHT; + break; + case ui::VirtualKey::kXInputPadDpadDown: + buttons |= X_INPUT_GAMEPAD_DPAD_DOWN; + break; + case ui::VirtualKey::kXInputPadDpadUp: + buttons |= X_INPUT_GAMEPAD_DPAD_UP; + break; + case ui::VirtualKey::kXInputPadRThumbPress: + buttons |= X_INPUT_GAMEPAD_RIGHT_THUMB; + break; + case ui::VirtualKey::kXInputPadLThumbPress: + buttons |= X_INPUT_GAMEPAD_LEFT_THUMB; + break; + case ui::VirtualKey::kXInputPadBack: + buttons |= X_INPUT_GAMEPAD_BACK; + break; + case ui::VirtualKey::kXInputPadStart: + buttons |= X_INPUT_GAMEPAD_START; + break; + case ui::VirtualKey::kXInputPadLShoulder: + buttons |= X_INPUT_GAMEPAD_LEFT_SHOULDER; + break; + case ui::VirtualKey::kXInputPadRShoulder: + buttons |= X_INPUT_GAMEPAD_RIGHT_SHOULDER; + break; + case ui::VirtualKey::kXInputPadLTrigger: + left_trigger = 0xFF; + break; + case ui::VirtualKey::kXInputPadRTrigger: + right_trigger = 0xFF; + break; + case ui::VirtualKey::kXInputPadLThumbLeft: + thumb_lx += SHRT_MIN; + break; + case ui::VirtualKey::kXInputPadLThumbRight: + thumb_lx += SHRT_MAX; + break; + case ui::VirtualKey::kXInputPadLThumbDown: + thumb_ly += SHRT_MIN; + break; + case ui::VirtualKey::kXInputPadLThumbUp: + thumb_ly += SHRT_MAX; + break; + case ui::VirtualKey::kXInputPadRThumbUp: + thumb_ry += SHRT_MAX; + break; + case ui::VirtualKey::kXInputPadRThumbDown: + thumb_ry += SHRT_MIN; + break; + case ui::VirtualKey::kXInputPadRThumbRight: + thumb_rx += SHRT_MAX; + break; + case ui::VirtualKey::kXInputPadRThumbLeft: + thumb_rx += SHRT_MIN; + break; + case ui::VirtualKey::kModifier: + modifier_pressed = true; + break; } } } + } out_state->packet_number = packet_number_; out_state->gamepad.buttons = buttons; @@ -650,29 +510,12 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, out_state->gamepad.thumb_rx = thumb_rx; out_state->gamepad.thumb_ry = thumb_ry; - // Check if we have any hooks/injections for the current game - bool game_modifier_handled = false; - if (xe::kernel::kernel_state()->has_executable_module()) - { - for (auto& game : hookable_games_) { - if (game->IsGameSupported()) { - std::unique_lock key_lock(key_mutex_); - game->DoHooks(user_index, state, out_state); - if (modifier_pressed) { - game_modifier_handled = - game->ModifierKeyHandler(user_index, state, out_state); - } - break; - } - } - } - - if (!game_modifier_handled && modifier_pressed) { - // Modifier not handled by any supported game class, apply default modifier - // (swap LS input to RS, for games that require RS movement) + if (modifier_pressed) { + // Swap LS input to RS out_state->gamepad.thumb_rx = out_state->gamepad.thumb_lx; out_state->gamepad.thumb_ry = out_state->gamepad.thumb_ly; - out_state->gamepad.thumb_lx = out_state->gamepad.thumb_ly = 0; + out_state->gamepad.thumb_lx = 0; + out_state->gamepad.thumb_ly = 0; } return result; @@ -743,92 +586,6 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, keystroke_flags |= 0x0020; // XINPUT_KEYSTROKE_ALT } } - - switch (evt.virtual_key) { - case ui::VirtualKey::kOem1: // ; - xinput_virtual_key = ui::VirtualKey::kXInputPadA; - break; - case ui::VirtualKey::kOem7: // ' - xinput_virtual_key = ui::VirtualKey::kXInputPadB; - break; - case ui::VirtualKey::kL: - xinput_virtual_key = ui::VirtualKey::kXInputPadX; - break; - case ui::VirtualKey::kP: - xinput_virtual_key = ui::VirtualKey::kXInputPadY; - break; - case ui::VirtualKey::k3: - xinput_virtual_key = ui::VirtualKey::kXInputPadRShoulder; - break; - case ui::VirtualKey::k1: - xinput_virtual_key = ui::VirtualKey::kXInputPadLShoulder; - break; - case ui::VirtualKey::kQ: - case ui::VirtualKey::kI: - xinput_virtual_key = ui::VirtualKey::kXInputPadLTrigger; - break; - case ui::VirtualKey::kE: - case ui::VirtualKey::kO: - xinput_virtual_key = ui::VirtualKey::kXInputPadRTrigger; - break; - case ui::VirtualKey::kX: - xinput_virtual_key = ui::VirtualKey::kXInputPadStart; - break; - case ui::VirtualKey::kZ: - xinput_virtual_key = ui::VirtualKey::kXInputPadBack; - break; - case ui::VirtualKey::kUp: - xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbUp; - break; - case ui::VirtualKey::kDown: - xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbDown; - break; - case ui::VirtualKey::kRight: - xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbRight; - break; - case ui::VirtualKey::kLeft: - xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbLeft; - break; - default: - // TODO(DrChat): Some other way to toggle this... - if (IS_KEY_TOGGLED(VK_CAPITAL) || IS_KEY_DOWN(VK_SHIFT)) { - // D-pad toggled. - switch (evt.virtual_key) { - case ui::VirtualKey::kW: - xinput_virtual_key = ui::VirtualKey::kXInputPadDpadUp; - break; - case ui::VirtualKey::kS: - xinput_virtual_key = ui::VirtualKey::kXInputPadDpadDown; - break; - case ui::VirtualKey::kA: - xinput_virtual_key = ui::VirtualKey::kXInputPadDpadLeft; - break; - case ui::VirtualKey::kD: - xinput_virtual_key = ui::VirtualKey::kXInputPadDpadRight; - break; - default: - break; - } - } else { - // Left thumbstick. - switch (evt.virtual_key) { - case ui::VirtualKey::kW: - xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbUp; - break; - case ui::VirtualKey::kS: - xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbDown; - break; - case ui::VirtualKey::kA: - xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbLeft; - break; - case ui::VirtualKey::kD: - xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbRight; - break; - default: - break; - } - } - } if (xinput_virtual_key != ui::VirtualKey::kNone) { if (evt.transition == true) { @@ -874,6 +631,21 @@ void WinKeyInputDriver::WinKeyWindowInputListener::OnKeyUp(ui::KeyEvent& e) { driver_.OnKey(e, false); } +void WinKeyInputDriver::WinKeyWindowInputListener::OnRawKeyboard( + ui::KeyEvent& e) { + driver_.OnRawKeyboard(e); +} + +void WinKeyInputDriver::OnRawKeyboard(ui::KeyEvent& e) { + if (!is_active()) { + return; + } + + const auto key = static_cast(e.virtual_key()); + + key_states_[key] = e.prev_state(); +} + void WinKeyInputDriver::OnKey(ui::KeyEvent& e, bool is_down) { if (!is_active()) { return; diff --git a/src/xenia/hid/winkey/winkey_input_driver.h b/src/xenia/hid/winkey/winkey_input_driver.h index b4c6710a1a..38843d5c2f 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.h +++ b/src/xenia/hid/winkey/winkey_input_driver.h @@ -15,26 +15,6 @@ #include "xenia/base/mutex.h" #include "xenia/hid/input_driver.h" #include "xenia/ui/virtual_key.h" -#include "xenia/hid/winkey/hookables/hookable_game.h" - -#define XINPUT_BUTTONS_MASK 0xFFFF -#define XINPUT_BIND_LEFT_TRIGGER (1 << 16) -#define XINPUT_BIND_RIGHT_TRIGGER (1 << 17) - -#define XINPUT_BIND_LS_UP (1 << 18) -#define XINPUT_BIND_LS_DOWN (1 << 19) -#define XINPUT_BIND_LS_LEFT (1 << 20) -#define XINPUT_BIND_LS_RIGHT (1 << 21) - -#define XINPUT_BIND_RS_UP (1 << 22) -#define XINPUT_BIND_RS_DOWN (1 << 23) -#define XINPUT_BIND_RS_LEFT (1 << 24) -#define XINPUT_BIND_RS_RIGHT (1 << 25) - -#define XINPUT_BIND_MODIFIER (1 << 26) - -#define VK_BIND_MWHEELUP 0x10000 -#define VK_BIND_MWHEELDOWN 0x20000 namespace xe { namespace hid { @@ -76,6 +56,7 @@ class WinKeyInputDriver final : public InputDriver { void OnKeyDown(ui::KeyEvent& e) override; void OnKeyUp(ui::KeyEvent& e) override; + void OnRawKeyboard(ui::KeyEvent& e) override; private: WinKeyInputDriver& driver_; @@ -85,6 +66,12 @@ class WinKeyInputDriver final : public InputDriver { const std::string_view description, const std::string_view binding); + ui::VirtualKey ParseButtonCombination(const char* combo); + + void ParseCustomKeyBinding(const std::string_view bindings_file); + + void OnRawKeyboard(ui::KeyEvent& e); + void OnKey(ui::KeyEvent& e, bool is_down); WinKeyWindowInputListener window_input_listener_; @@ -94,18 +81,10 @@ class WinKeyInputDriver final : public InputDriver { std::vector key_bindings_; uint8_t key_map_[256]; - std::mutex mouse_mutex_; - std::queue mouse_events_; - - std::mutex key_mutex_; - bool key_states_[256]; + uint8_t key_states_[256] = {}; + std::map> key_binds_; uint32_t packet_number_ = 1; - - std::vector> hookable_games_; - - std::unordered_map> - key_binds_; }; } // namespace winkey diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 0a2c12788b..8b9bbe34f0 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -321,14 +321,6 @@ object_ref KernelState::GetExecutableModule() { return executable_module_; } -bool KernelState::has_executable_module() -{ - if (executable_module_) { - return true; - } - return false; -} - void KernelState::SetExecutableModule(object_ref module) { if (module.get() == executable_module_.get()) { return; diff --git a/src/xenia/kernel/kernel_state.h b/src/xenia/kernel/kernel_state.h index f8e2dc5522..d04a4cee2a 100644 --- a/src/xenia/kernel/kernel_state.h +++ b/src/xenia/kernel/kernel_state.h @@ -232,7 +232,6 @@ class KernelState { object_ref LaunchModule(object_ref module); object_ref GetExecutableModule(); - bool has_executable_module(); void SetExecutableModule(object_ref module); object_ref LoadUserModule(const std::string_view name, bool call_entry = true); diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index 94132dc2f3..f4e8a53f06 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -806,14 +806,10 @@ static dword_result_t XamShowMessageBoxUi( auto title_id = kernel_state()->title_id(); X_RESULT result; - if (cvars::headless || title_id == 0x584109C2) { - uint32_t active_btn = active_button; - if (title_id == 0x584109C2 && active_btn == 0) { - active_btn = 1; - } + if (cvars::headless) { // Auto-pick the focused button. - auto run = [result_ptr, active_btn]() -> X_RESULT { - *result_ptr = static_cast(active_btn); + auto run = [result_ptr, active_button]() -> X_RESULT { + *result_ptr = static_cast(active_button); return X_ERROR_SUCCESS; }; result = xeXamDispatchHeadless(run, overlapped); diff --git a/src/xenia/premake5.lua b/src/xenia/premake5.lua index ccebb047bc..4d01ea74e2 100644 --- a/src/xenia/premake5.lua +++ b/src/xenia/premake5.lua @@ -9,7 +9,6 @@ project("xenia-core") links({ "fmt", "xenia-base", - "xenia-patcher", }) defines({ }) diff --git a/src/xenia/ui/virtual_key.h b/src/xenia/ui/virtual_key.h index e2491f69cf..e062dca3a1 100644 --- a/src/xenia/ui/virtual_key.h +++ b/src/xenia/ui/virtual_key.h @@ -357,6 +357,8 @@ enum class VirtualKey : uint16_t { kXInputPadRThumbDownLeft = 0x5837, // Undocumented therefore kNone however using 0x5838 for now. kXInputPadGuide = 0x5838, + + kModifier = 0x5841 }; } // namespace ui diff --git a/src/xenia/ui/window.cc b/src/xenia/ui/window.cc index c70cd7d9c8..d7f106e70d 100644 --- a/src/xenia/ui/window.cc +++ b/src/xenia/ui/window.cc @@ -556,10 +556,6 @@ void Window::OnFileDrop(FileDropEvent& e, void Window::OnKeyDown(KeyEvent& e, WindowDestructionReceiver& destruction_receiver) { - on_key_down(e); - if (e.is_handled()) { - return; - } PropagateEventThroughInputListeners( [&e](auto listener) { listener->OnKeyDown(e); @@ -573,10 +569,6 @@ void Window::OnKeyDown(KeyEvent& e, void Window::OnKeyUp(KeyEvent& e, WindowDestructionReceiver& destruction_receiver) { - on_key_up(e); - if (e.is_handled()) { - return; - } PropagateEventThroughInputListeners( [&e](auto listener) { listener->OnKeyUp(e); @@ -590,10 +582,6 @@ void Window::OnKeyUp(KeyEvent& e, void Window::OnKeyChar(KeyEvent& e, WindowDestructionReceiver& destruction_receiver) { - on_key_char(e); - if (e.is_handled()) { - return; - } PropagateEventThroughInputListeners( [&e](auto listener) { listener->OnKeyChar(e); @@ -607,10 +595,6 @@ void Window::OnKeyChar(KeyEvent& e, void Window::OnMouseDown(MouseEvent& e, WindowDestructionReceiver& destruction_receiver) { - on_mouse_down(e); - if (e.is_handled()) { - return; - } PropagateEventThroughInputListeners( [&e](auto listener) { listener->OnMouseDown(e); @@ -624,10 +608,6 @@ void Window::OnMouseDown(MouseEvent& e, void Window::OnMouseMove(MouseEvent& e, WindowDestructionReceiver& destruction_receiver) { - on_mouse_move(e); - if (e.is_handled()) { - return; - } PropagateEventThroughInputListeners( [&e](auto listener) { listener->OnMouseMove(e); @@ -641,12 +621,7 @@ void Window::OnMouseMove(MouseEvent& e, void Window::OnMouseUp(MouseEvent& e, WindowDestructionReceiver& destruction_receiver) { - on_mouse_up(e); - if (e.is_handled()) { - return; - } PropagateEventThroughInputListeners( - [&e](auto listener) { listener->OnMouseUp(e); return e.is_handled(); @@ -659,10 +634,6 @@ void Window::OnMouseUp(MouseEvent& e, void Window::OnMouseWheel(MouseEvent& e, WindowDestructionReceiver& destruction_receiver) { - on_mouse_wheel(e); - if (e.is_handled()) { - return; - } PropagateEventThroughInputListeners( [&e](auto listener) { listener->OnMouseWheel(e); @@ -674,29 +645,8 @@ void Window::OnMouseWheel(MouseEvent& e, } } -void Window::OnRawMouse(MouseEvent& e, - WindowDestructionReceiver& destruction_receiver) { - on_raw_mouse(e); - if (e.is_handled()) { - return; - } - PropagateEventThroughInputListeners( - [&e](auto listener) { - listener->OnRawMouse(e); - return e.is_handled(); - }, - destruction_receiver); - if (destruction_receiver.IsWindowDestroyed()) { - return; - } -} - void Window::OnRawKeyboard(KeyEvent& e, WindowDestructionReceiver& destruction_receiver) { - on_raw_keyboard(e); - if (e.is_handled()) { - return; - } PropagateEventThroughInputListeners( [&e](auto listener) { listener->OnRawKeyboard(e); diff --git a/src/xenia/ui/window.h b/src/xenia/ui/window.h index 11eba4c9ce..d127dd3608 100644 --- a/src/xenia/ui/window.h +++ b/src/xenia/ui/window.h @@ -17,7 +17,6 @@ #include #include -#include "xenia/base/delegate.h" #include "xenia/base/platform.h" #include "xenia/ui/menu_item.h" #include "xenia/ui/presenter.h" @@ -295,7 +294,7 @@ class Window { // Provide null buffer and / or zero size to reset the icon. void SetIcon(const void* buffer, size_t size); void ResetIcon() { SetIcon(nullptr, 0); } - + // Desired state stored by the common Window, externally modifiable, read-only // in the implementation. void SetMainMenu(std::unique_ptr new_main_menu); @@ -349,18 +348,6 @@ class Window { presenter_->RequestUIPaintFromUIThread(); } } - - Delegate on_key_down; - Delegate on_key_up; - Delegate on_key_char; - - Delegate on_mouse_down; - Delegate on_mouse_move; - Delegate on_mouse_up; - Delegate on_mouse_wheel; - - Delegate on_raw_mouse; - Delegate on_raw_keyboard; protected: // The receiver, which must never be instantiated in the Window object itself @@ -613,8 +600,6 @@ class Window { void OnTouchEvent(TouchEvent& e, WindowDestructionReceiver& destruction_receiver); - void OnRawMouse(MouseEvent& e, - WindowDestructionReceiver& destruction_receiver); void OnRawKeyboard(KeyEvent& e, WindowDestructionReceiver& destruction_receiver); private: diff --git a/src/xenia/ui/window_listener.h b/src/xenia/ui/window_listener.h index 6f608d2624..77dbe26aa0 100644 --- a/src/xenia/ui/window_listener.h +++ b/src/xenia/ui/window_listener.h @@ -49,7 +49,6 @@ class WindowInputListener { virtual void OnMouseUp(MouseEvent& e) {} virtual void OnMouseWheel(MouseEvent& e) {} - virtual void OnRawMouse(MouseEvent& e) {} virtual void OnRawKeyboard(KeyEvent& e) {} virtual void OnTouchEvent(TouchEvent& e) {} diff --git a/src/xenia/ui/window_win.cc b/src/xenia/ui/window_win.cc index 4678a1cc34..b1433136a4 100644 --- a/src/xenia/ui/window_win.cc +++ b/src/xenia/ui/window_win.cc @@ -206,15 +206,10 @@ bool Win32Window::OpenImpl() { // Enable file dragging from external sources DragAcceptFiles(hwnd_, true); - - // Enable raw input for mouse & keyboard + + // Enable raw input for keyboard RAWINPUTDEVICE device; device.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC - device.usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE - device.dwFlags = 0; - device.hwndTarget = 0; - RegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE)); - device.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC device.usUsage = 0x06; // HID_USAGE_GENERIC_KEYBOARD device.dwFlags = 0; device.hwndTarget = 0; @@ -344,8 +339,6 @@ void Win32Window::ApplyNewFullscreen() { if (destruction_receiver.IsWindowDestroyedOrClosed()) { return; } - - ToggleCursorLock(true); } else { // Changing the style and the menu may change the size too, don't handle // the resize multiple times (also potentially with the listeners changing @@ -429,8 +422,6 @@ void Win32Window::ApplyNewFullscreen() { if (destruction_receiver.IsWindowDestroyedOrClosed()) { return; } - - ToggleCursorLock(false); } } @@ -1032,7 +1023,7 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, } OnAfterClose(); } break; - case WM_INPUT: { + case WM_INPUT: { HRAWINPUT hRawInput = (HRAWINPUT)lParam; UINT dataSize = 0; @@ -1053,130 +1044,121 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, break; } - if (rawinput_data_.header.dwType == RIM_TYPEMOUSE) { - const auto& mouseData = rawinput_data_.data.mouse; - - auto e = MouseEvent(this, MouseEvent::Button::kNone, mouseData.lLastX, - mouseData.lLastY, mouseData.usButtonFlags, - (int16_t)mouseData.usButtonData); - WindowDestructionReceiver destruction_receiver(this); - OnRawMouse(e, destruction_receiver); - return 0; - } else if (rawinput_data_.header.dwType == RIM_TYPEKEYBOARD) { + if (rawinput_data_.header.dwType == RIM_TYPEKEYBOARD) { const auto& keyData = rawinput_data_.data.keyboard; // Adjust VK code passed to handlers // Based on // https://blog.molecular-matters.com/2011/09/05/properly-handling-keyboard-input/ - ui::VirtualKey vkey = (ui::VirtualKey)keyData.VKey; + ui::VirtualKey vkey = static_cast(keyData.VKey); bool isE0 = (keyData.Flags & RI_KEY_E0) != 0; // discard "fake keys" which are part of an escaped sequence - if (vkey == (ui::VirtualKey)255) { + if (vkey == static_cast(255)) { return 0; - } else if (vkey == ui::VirtualKey::kShift) { - // correct left-hand / right-hand SHIFT - vkey = (ui::VirtualKey)MapVirtualKey(keyData.MakeCode, - MAPVK_VSC_TO_VK_EX); - } else { - switch (vkey) { - // right-hand CONTROL and ALT have their e0 bit set - case ui::VirtualKey::kControl: - vkey = - isE0 ? ui::VirtualKey::kRControl : ui::VirtualKey::kLControl; - break; + } - case ui::VirtualKey::kMenu: - vkey = isE0 ? ui::VirtualKey::kRMenu : ui::VirtualKey::kLMenu; - break; + switch (vkey) { + // correct left-hand / right-hand SHIFT + case ui::VirtualKey::kShift: + vkey = static_cast( + MapVirtualKey(keyData.MakeCode, MAPVK_VSC_TO_VK_EX)); + break; - case ui::VirtualKey::kReturn: - if (isE0) { - vkey = ui::VirtualKey::kSeparator; - } - break; + // right-hand CONTROL and ALT have their e0 bit set + case ui::VirtualKey::kControl: + vkey = isE0 ? ui::VirtualKey::kRControl : ui::VirtualKey::kLControl; + break; - // the standard INSERT, DELETE, HOME, END, PRIOR and NEXT keys will - // always have their e0 bit set, but the corresponding keys on the - // NUMPAD will not. - case ui::VirtualKey::kInsert: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad0; - } - break; + case ui::VirtualKey::kMenu: + vkey = isE0 ? ui::VirtualKey::kRMenu : ui::VirtualKey::kLMenu; + break; - case ui::VirtualKey::kDelete: - if (!isE0) { - vkey = ui::VirtualKey::kDecimal; - } - break; + case ui::VirtualKey::kReturn: + if (isE0) { + vkey = ui::VirtualKey::kSeparator; + } + break; - case ui::VirtualKey::kHome: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad7; - } - break; + // the standard INSERT, DELETE, HOME, END, PRIOR and NEXT keys will + // always have their e0 bit set, but the corresponding keys on the + // NUMPAD will not. + case ui::VirtualKey::kInsert: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad0; + } + break; - case ui::VirtualKey::kEnd: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad1; - } - break; + case ui::VirtualKey::kDelete: + if (!isE0) { + vkey = ui::VirtualKey::kDecimal; + } + break; - case ui::VirtualKey::kPrior: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad9; - } - break; + case ui::VirtualKey::kHome: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad7; + } + break; - case ui::VirtualKey::kNext: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad3; - } - break; + case ui::VirtualKey::kEnd: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad1; + } + break; - // the standard arrow keys will always have their e0 bit set, but - // the corresponding keys on the NUMPAD will not. - case ui::VirtualKey::kLeft: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad4; - } - break; + case ui::VirtualKey::kPrior: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad9; + } + break; - case ui::VirtualKey::kRight: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad6; - } - break; + case ui::VirtualKey::kNext: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad3; + } + break; - case ui::VirtualKey::kUp: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad8; - } - break; + // the standard arrow keys will always have their e0 bit set, but + // the corresponding keys on the NUMPAD will not. + case ui::VirtualKey::kLeft: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad4; + } + break; - case ui::VirtualKey::kDown: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad2; - } - break; + case ui::VirtualKey::kRight: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad6; + } + break; - // NUMPAD 5 doesn't have its e0 bit set - case ui::VirtualKey::kClear: - if (!isE0) { - vkey = ui::VirtualKey::kNumpad5; - } - break; - } + case ui::VirtualKey::kUp: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad8; + } + break; + + case ui::VirtualKey::kDown: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad2; + } + break; + + // NUMPAD 5 doesn't have its e0 bit set + case ui::VirtualKey::kClear: + if (!isE0) { + vkey = ui::VirtualKey::kNumpad5; + } + break; } auto e = KeyEvent(this, vkey, 0, !(keyData.Flags & RI_KEY_BREAK), false, false, false, false); - WindowDestructionReceiver destruction_receiver(this); + WindowDestructionReceiver destruction_receiver(this); OnRawKeyboard(e, destruction_receiver); return 0; } - } break; case WM_DROPFILES: { HDROP drop_handle = reinterpret_cast(wParam); @@ -1288,10 +1270,6 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, } break; case WM_KILLFOCUS: { - if (IsFullscreen()) { - ToggleCursorLock(false); - } - WindowDestructionReceiver destruction_receiver(this); OnFocusUpdate(false, destruction_receiver); if (destruction_receiver.IsWindowDestroyedOrClosed()) { @@ -1300,10 +1278,6 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, } break; case WM_SETFOCUS: { - if (IsFullscreen()) { - ToggleCursorLock(true); - } - WindowDestructionReceiver destruction_receiver(this); OnFocusUpdate(true, destruction_receiver); if (destruction_receiver.IsWindowDestroyedOrClosed()) { @@ -1357,6 +1331,7 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, } return 0; } break; + case WM_TABLET_QUERYSYSTEMGESTURESTATUS: return // disables press and hold (right-click) gesture @@ -1441,24 +1416,6 @@ LRESULT CALLBACK Win32Window::WndProcThunk(HWND hWnd, UINT message, return DefWindowProc(hWnd, message, wParam, lParam); } -void Win32Window::ToggleCursorLock(bool lock) { - if (lock) { - // Cursor bounds can be lost when focus is lost, reapply them... - RECT bounds; - GetWindowRect(hwnd(), &bounds); - - // Reduce cursor bounds by 1px on each side, just in case.. - bounds.top++; - bounds.left++; - bounds.bottom--; - bounds.right--; - - ClipCursor(&bounds); - } else { - ClipCursor(NULL); - } -} - std::unique_ptr MenuItem::Create(Type type, const std::string& text, const std::string& hotkey, diff --git a/src/xenia/ui/window_win.h b/src/xenia/ui/window_win.h index e27952cbf6..e0a39c0f0b 100644 --- a/src/xenia/ui/window_win.h +++ b/src/xenia/ui/window_win.h @@ -95,7 +95,6 @@ class Win32Window : public Window { static LRESULT CALLBACK WndProcThunk(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - void ToggleCursorLock(bool lock); // This can't handle messages sent during CreateWindow (hwnd_ still not // assigned to) or after nulling hwnd_ in closing / deleting. virtual LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam,