diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index 76614a2dd..67d3a39b7 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -59,6 +59,9 @@ DECLARE_bool(d3d12_clear_memory_page_state); DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.", "Display"); +DEFINE_bool(controller_hotkeys, true, + "Toggle hotkeys for Xbox and PS controllers.", "General"); + DEFINE_string( postprocess_antialiasing, "", "Post-processing anti-aliasing effect to apply to the image output of the " @@ -244,7 +247,9 @@ void EmulatorWindow::OnEmulatorInitialized() { } if (IsUseNexusForGameBarEnabled()) { - XELOGE("Xbox Gamebar Enabled, using BACK button instead of GUIDE!!!"); + XELOGE( + "Xbox Gamebar Enabled, using BACK button instead of GUIDE for " + "controller hotkeys!!!"); } // Create a thread to listen for controller hotkeys. @@ -1217,8 +1222,11 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey( // Do not activate hotkeys that are not intended for activation during // gameplay - if (emulator_->is_title_open() && !it->second.title_passthru) { - return Unknown_hotkey; + if (emulator_->is_title_open()) { + // If non-pass through (menu hoykeys) or hotkeys disabled then return + if (!it->second.title_passthru || !cvars::controller_hotkeys) { + return Unknown_hotkey; + } } EmulatorWindow::ControllerHotKey button_combination = it->second; @@ -1239,9 +1247,7 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey( if (title_success == X_ERROR_SUCCESS) { imgui_drawer_.get()->ClearDialogs(); } - } - // RunPreviouslyPlayedTitle(); - break; + } break; case ButtonFunctions::ClearMemoryPageState: ToggleGPUSetting(gpu_cvar::ClearMemoryPageState); @@ -1346,9 +1352,6 @@ void EmulatorWindow::GamepadHotKeys() { auto input_sys = emulator_->input_system(); - // uint8_t users = emulator_->kernel_state()->GetConnectedUsers(); - // uint8_t users = input_sys->GetConnectedSlots(); - if (input_sys) { while (true) { auto input_lock = input_sys->lock(); @@ -1356,11 +1359,11 @@ void EmulatorWindow::GamepadHotKeys() { for (uint32_t user_index = 0; user_index < MAX_USERS; ++user_index) { X_RESULT result = input_sys->GetState(user_index, &state); + // Release the lock before processing the hotkey + input_lock.mutex()->unlock(); + // Check if the controller is connected if (result == X_ERROR_SUCCESS) { - // Release the lock before processing the hotkey - input_lock.mutex()->unlock(); - if (ProcessControllerHotkey(state.gamepad.buttons).rumble) { // Enable Vibration VibrateController(input_sys, user_index, true); @@ -1407,6 +1410,10 @@ bool EmulatorWindow::IsUseNexusForGameBarEnabled() { #endif } +std::string EmulatorWindow::BoolToString(bool value) { + return std::string(value ? "true" : "false"); +} + void EmulatorWindow::DisplayHotKeysConfig() { std::string msg = ""; std::string msg_passthru = ""; @@ -1427,6 +1434,10 @@ void EmulatorWindow::DisplayHotKeysConfig() { pretty_text += " (Disabled)"; } + if (val.title_passthru && !cvars::controller_hotkeys) { + pretty_text += " (Disabled)"; + } + if (val.title_passthru) { msg += pretty_text + "\n"; } else { @@ -1440,16 +1451,18 @@ void EmulatorWindow::DisplayHotKeysConfig() { // Prepend non-passthru hotkeys msg_passthru += "\n"; msg.insert(0, msg_passthru); - msg += "\n"; - msg += "Readback Resolve: " + - std::string(cvars::d3d12_readback_resolve ? "true\n" : "false\n"); - msg += - "Clear Memory Page State: " + - std::string(cvars::d3d12_clear_memory_page_state ? "true\n" : "false\n"); + + msg += "Readback Resolve: " + BoolToString(cvars::d3d12_readback_resolve); + msg += "\n"; + + msg += "Clear Memory Page State: " + + BoolToString(cvars::d3d12_clear_memory_page_state); + msg += "\n"; + + msg += "Controller Hotkeys: " + BoolToString(cvars::controller_hotkeys); imgui_drawer_.get()->ClearDialogs(); - xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer_.get(), "Controller Hotkeys", msg); } @@ -1488,6 +1501,8 @@ xe::X_STATUS EmulatorWindow::RunTitle(std::filesystem::path path) { if (result) { XELOGE("Failed to launch target: {:08X}", result); + imgui_drawer_.get()->ClearDialogs(); + xe::ui::ImGuiDialog::ShowMessageBox( imgui_drawer_.get(), "Title Launch Failed!", "Failed to launch title.\n\nCheck xenia.log for technical details."); diff --git a/src/xenia/app/emulator_window.h b/src/xenia/app/emulator_window.h index 60990554f..d49c9f846 100644 --- a/src/xenia/app/emulator_window.h +++ b/src/xenia/app/emulator_window.h @@ -208,6 +208,7 @@ class EmulatorWindow { void GamepadHotKeys(); void ToggleGPUSetting(gpu_cvar index); bool IsUseNexusForGameBarEnabled(); + std::string BoolToString(bool value); void DisplayHotKeysConfig(); xe::X_STATUS RunTitle(std::filesystem::path path); diff --git a/src/xenia/hid/xinput/xinput_input_driver.cc b/src/xenia/hid/xinput/xinput_input_driver.cc index 6a92fa0fb..51f390117 100644 --- a/src/xenia/hid/xinput/xinput_input_driver.cc +++ b/src/xenia/hid/xinput/xinput_input_driver.cc @@ -52,6 +52,7 @@ X_STATUS XInputInputDriver::Setup() { } // Support guide button with XInput using XInputGetStateEx + // https://source.winehq.org/git/wine.git/?a=commit;h=de3591ca9803add117fbacb8abe9b335e2e44977 auto const XInputGetStateEx = (LPCSTR)100; // Required. @@ -77,7 +78,7 @@ X_STATUS XInputInputDriver::Setup() { XInputGetKeystroke_ = xigk; XInputSetState_ = xiss; XInputEnable_ = xie; - + return X_STATUS_SUCCESS; } @@ -140,16 +141,17 @@ X_RESULT XInputInputDriver::GetState(uint32_t user_index, if (skipper) { return skipper; } - + + // Added padding in case we are using XInputGetStateEx struct { XINPUT_STATE state; - unsigned int xinput_state_ex_padding; // Add padding in case we are using XInputGetStateEx + unsigned int dwPaddingReserved; } native_state; - // If the guide button is enabled use XInputGetStateEx, otherwise use the default XInputGetState. - auto xigs = cvars::guide_button - ? (decltype(&XInputGetState))XInputGetStateEx_ - : (decltype(&XInputGetState))XInputGetState_; + // If the guide button is enabled use XInputGetStateEx, otherwise use the + // default XInputGetState. + auto xigs = cvars::guide_button ? (decltype(&XInputGetState))XInputGetStateEx_ + : (decltype(&XInputGetState))XInputGetState_; DWORD result = xigs(user_index, &native_state.state); if (result) {