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:
parent
89f3598426
commit
b10c84b340
|
@ -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.");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue