Added controller hotkeys cvar (#119)

* Added controller hotkeys setting

Added option to disable controller hotkeys
Minor Changes

* Fixed locked input system

The input system lock should be released even if a controller is not connected.
This commit is contained in:
Adrian 2023-01-29 18:26:25 +00:00 committed by GitHub
parent 89f3598426
commit b10c84b340
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 26 deletions

View File

@ -59,6 +59,9 @@ DECLARE_bool(d3d12_clear_memory_page_state);
DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.", DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.",
"Display"); "Display");
DEFINE_bool(controller_hotkeys, true,
"Toggle hotkeys for Xbox and PS controllers.", "General");
DEFINE_string( DEFINE_string(
postprocess_antialiasing, "", postprocess_antialiasing, "",
"Post-processing anti-aliasing effect to apply to the image output of the " "Post-processing anti-aliasing effect to apply to the image output of the "
@ -244,7 +247,9 @@ void EmulatorWindow::OnEmulatorInitialized() {
} }
if (IsUseNexusForGameBarEnabled()) { 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. // 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 // Do not activate hotkeys that are not intended for activation during
// gameplay // gameplay
if (emulator_->is_title_open() && !it->second.title_passthru) { if (emulator_->is_title_open()) {
return Unknown_hotkey; // 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; EmulatorWindow::ControllerHotKey button_combination = it->second;
@ -1239,9 +1247,7 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
if (title_success == X_ERROR_SUCCESS) { if (title_success == X_ERROR_SUCCESS) {
imgui_drawer_.get()->ClearDialogs(); imgui_drawer_.get()->ClearDialogs();
} }
} } break;
// RunPreviouslyPlayedTitle();
break;
case ButtonFunctions::ClearMemoryPageState: case ButtonFunctions::ClearMemoryPageState:
ToggleGPUSetting(gpu_cvar::ClearMemoryPageState); ToggleGPUSetting(gpu_cvar::ClearMemoryPageState);
@ -1346,9 +1352,6 @@ void EmulatorWindow::GamepadHotKeys() {
auto input_sys = emulator_->input_system(); auto input_sys = emulator_->input_system();
// uint8_t users = emulator_->kernel_state()->GetConnectedUsers();
// uint8_t users = input_sys->GetConnectedSlots();
if (input_sys) { if (input_sys) {
while (true) { while (true) {
auto input_lock = input_sys->lock(); 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) { for (uint32_t user_index = 0; user_index < MAX_USERS; ++user_index) {
X_RESULT result = input_sys->GetState(user_index, &state); 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 // Check if the controller is connected
if (result == X_ERROR_SUCCESS) { if (result == X_ERROR_SUCCESS) {
// Release the lock before processing the hotkey
input_lock.mutex()->unlock();
if (ProcessControllerHotkey(state.gamepad.buttons).rumble) { if (ProcessControllerHotkey(state.gamepad.buttons).rumble) {
// Enable Vibration // Enable Vibration
VibrateController(input_sys, user_index, true); VibrateController(input_sys, user_index, true);
@ -1407,6 +1410,10 @@ bool EmulatorWindow::IsUseNexusForGameBarEnabled() {
#endif #endif
} }
std::string EmulatorWindow::BoolToString(bool value) {
return std::string(value ? "true" : "false");
}
void EmulatorWindow::DisplayHotKeysConfig() { void EmulatorWindow::DisplayHotKeysConfig() {
std::string msg = ""; std::string msg = "";
std::string msg_passthru = ""; std::string msg_passthru = "";
@ -1427,6 +1434,10 @@ void EmulatorWindow::DisplayHotKeysConfig() {
pretty_text += " (Disabled)"; pretty_text += " (Disabled)";
} }
if (val.title_passthru && !cvars::controller_hotkeys) {
pretty_text += " (Disabled)";
}
if (val.title_passthru) { if (val.title_passthru) {
msg += pretty_text + "\n"; msg += pretty_text + "\n";
} else { } else {
@ -1440,16 +1451,18 @@ void EmulatorWindow::DisplayHotKeysConfig() {
// Prepend non-passthru hotkeys // Prepend non-passthru hotkeys
msg_passthru += "\n"; msg_passthru += "\n";
msg.insert(0, msg_passthru); msg.insert(0, msg_passthru);
msg += "\n"; msg += "\n";
msg += "Readback Resolve: " +
std::string(cvars::d3d12_readback_resolve ? "true\n" : "false\n"); msg += "Readback Resolve: " + BoolToString(cvars::d3d12_readback_resolve);
msg += msg += "\n";
"Clear Memory Page State: " +
std::string(cvars::d3d12_clear_memory_page_state ? "true\n" : "false\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(); imgui_drawer_.get()->ClearDialogs();
xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer_.get(), "Controller Hotkeys", xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer_.get(), "Controller Hotkeys",
msg); msg);
} }
@ -1488,6 +1501,8 @@ xe::X_STATUS EmulatorWindow::RunTitle(std::filesystem::path path) {
if (result) { if (result) {
XELOGE("Failed to launch target: {:08X}", result); XELOGE("Failed to launch target: {:08X}", result);
imgui_drawer_.get()->ClearDialogs();
xe::ui::ImGuiDialog::ShowMessageBox( xe::ui::ImGuiDialog::ShowMessageBox(
imgui_drawer_.get(), "Title Launch Failed!", imgui_drawer_.get(), "Title Launch Failed!",
"Failed to launch title.\n\nCheck xenia.log for technical details."); "Failed to launch title.\n\nCheck xenia.log for technical details.");

View File

@ -208,6 +208,7 @@ class EmulatorWindow {
void GamepadHotKeys(); void GamepadHotKeys();
void ToggleGPUSetting(gpu_cvar index); void ToggleGPUSetting(gpu_cvar index);
bool IsUseNexusForGameBarEnabled(); bool IsUseNexusForGameBarEnabled();
std::string BoolToString(bool value);
void DisplayHotKeysConfig(); void DisplayHotKeysConfig();
xe::X_STATUS RunTitle(std::filesystem::path path); xe::X_STATUS RunTitle(std::filesystem::path path);

View File

@ -52,6 +52,7 @@ X_STATUS XInputInputDriver::Setup() {
} }
// Support guide button with XInput using XInputGetStateEx // Support guide button with XInput using XInputGetStateEx
// https://source.winehq.org/git/wine.git/?a=commit;h=de3591ca9803add117fbacb8abe9b335e2e44977
auto const XInputGetStateEx = (LPCSTR)100; auto const XInputGetStateEx = (LPCSTR)100;
// Required. // Required.
@ -77,7 +78,7 @@ X_STATUS XInputInputDriver::Setup() {
XInputGetKeystroke_ = xigk; XInputGetKeystroke_ = xigk;
XInputSetState_ = xiss; XInputSetState_ = xiss;
XInputEnable_ = xie; XInputEnable_ = xie;
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
} }
@ -140,16 +141,17 @@ X_RESULT XInputInputDriver::GetState(uint32_t user_index,
if (skipper) { if (skipper) {
return skipper; return skipper;
} }
// Added padding in case we are using XInputGetStateEx
struct { struct {
XINPUT_STATE state; XINPUT_STATE state;
unsigned int xinput_state_ex_padding; // Add padding in case we are using XInputGetStateEx unsigned int dwPaddingReserved;
} native_state; } native_state;
// If the guide button is enabled use XInputGetStateEx, otherwise use the default XInputGetState. // If the guide button is enabled use XInputGetStateEx, otherwise use the
auto xigs = cvars::guide_button // default XInputGetState.
? (decltype(&XInputGetState))XInputGetStateEx_ auto xigs = cvars::guide_button ? (decltype(&XInputGetState))XInputGetStateEx_
: (decltype(&XInputGetState))XInputGetState_; : (decltype(&XInputGetState))XInputGetState_;
DWORD result = xigs(user_index, &native_state.state); DWORD result = xigs(user_index, &native_state.state);
if (result) { if (result) {