summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/am/applets/applet_controller.cpp21
-rw-r--r--src/core/hle/service/am/applets/applet_controller.h15
-rw-r--r--src/input_common/sdl/sdl_impl.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp56
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp44
-rw-r--r--src/yuzu/configuration/configure_input_player.ui44
-rw-r--r--src/yuzu_cmd/config.cpp1
-rw-r--r--src/yuzu_cmd/default_ini.h4
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp44
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp6
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h2
-rw-r--r--src/yuzu_cmd/yuzu.cpp2
12 files changed, 200 insertions, 45 deletions
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 12682effe..2721679c1 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -87,6 +87,10 @@ void Controller::Initialize() {
87 case sizeof(ControllerUpdateFirmwareArg): 87 case sizeof(ControllerUpdateFirmwareArg):
88 controller_private_arg.mode = ControllerSupportMode::ShowControllerFirmwareUpdate; 88 controller_private_arg.mode = ControllerSupportMode::ShowControllerFirmwareUpdate;
89 break; 89 break;
90 case sizeof(ControllerKeyRemappingArg):
91 controller_private_arg.mode =
92 ControllerSupportMode::ShowControllerKeyRemappingForSystem;
93 break;
90 default: 94 default:
91 UNIMPLEMENTED_MSG("Unknown ControllerPrivateArg mode={} with arg_size={}", 95 UNIMPLEMENTED_MSG("Unknown ControllerPrivateArg mode={} with arg_size={}",
92 controller_private_arg.mode, controller_private_arg.arg_size); 96 controller_private_arg.mode, controller_private_arg.arg_size);
@@ -99,7 +103,9 @@ void Controller::Initialize() {
99 // This is always 0 (Application) except with ShowControllerFirmwareUpdateForSystem. 103 // This is always 0 (Application) except with ShowControllerFirmwareUpdateForSystem.
100 if (controller_private_arg.caller >= ControllerSupportCaller::MaxControllerSupportCaller) { 104 if (controller_private_arg.caller >= ControllerSupportCaller::MaxControllerSupportCaller) {
101 if (controller_private_arg.flag_1 && 105 if (controller_private_arg.flag_1 &&
102 controller_private_arg.mode == ControllerSupportMode::ShowControllerFirmwareUpdate) { 106 (controller_private_arg.mode == ControllerSupportMode::ShowControllerFirmwareUpdate ||
107 controller_private_arg.mode ==
108 ControllerSupportMode::ShowControllerKeyRemappingForSystem)) {
103 controller_private_arg.caller = ControllerSupportCaller::System; 109 controller_private_arg.caller = ControllerSupportCaller::System;
104 } else { 110 } else {
105 controller_private_arg.caller = ControllerSupportCaller::Application; 111 controller_private_arg.caller = ControllerSupportCaller::Application;
@@ -121,6 +127,7 @@ void Controller::Initialize() {
121 std::memcpy(&controller_user_arg_old, user_arg.data(), user_arg.size()); 127 std::memcpy(&controller_user_arg_old, user_arg.data(), user_arg.size());
122 break; 128 break;
123 case ControllerAppletVersion::Version7: 129 case ControllerAppletVersion::Version7:
130 case ControllerAppletVersion::Version8:
124 ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew)); 131 ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew));
125 std::memcpy(&controller_user_arg_new, user_arg.data(), user_arg.size()); 132 std::memcpy(&controller_user_arg_new, user_arg.data(), user_arg.size());
126 break; 133 break;
@@ -143,6 +150,16 @@ void Controller::Initialize() {
143 std::memcpy(&controller_update_arg, update_arg.data(), update_arg.size()); 150 std::memcpy(&controller_update_arg, update_arg.data(), update_arg.size());
144 break; 151 break;
145 } 152 }
153 case ControllerSupportMode::ShowControllerKeyRemappingForSystem: {
154 const auto remapping_arg_storage = broker.PopNormalDataToApplet();
155 ASSERT(remapping_arg_storage != nullptr);
156
157 const auto& remapping_arg = remapping_arg_storage->GetData();
158 ASSERT(remapping_arg.size() == sizeof(ControllerKeyRemappingArg));
159
160 std::memcpy(&controller_key_remapping_arg, remapping_arg.data(), remapping_arg.size());
161 break;
162 }
146 default: { 163 default: {
147 UNIMPLEMENTED_MSG("Unimplemented ControllerSupportMode={}", controller_private_arg.mode); 164 UNIMPLEMENTED_MSG("Unimplemented ControllerSupportMode={}", controller_private_arg.mode);
148 break; 165 break;
@@ -179,6 +196,7 @@ void Controller::Execute() {
179 std::vector<ExplainText>(controller_user_arg_old.explain_text.begin(), 196 std::vector<ExplainText>(controller_user_arg_old.explain_text.begin(),
180 controller_user_arg_old.explain_text.end())); 197 controller_user_arg_old.explain_text.end()));
181 case ControllerAppletVersion::Version7: 198 case ControllerAppletVersion::Version7:
199 case ControllerAppletVersion::Version8:
182 default: 200 default:
183 return ConvertToFrontendParameters( 201 return ConvertToFrontendParameters(
184 controller_private_arg, controller_user_arg_new.header, 202 controller_private_arg, controller_user_arg_new.header,
@@ -210,6 +228,7 @@ void Controller::Execute() {
210 } 228 }
211 case ControllerSupportMode::ShowControllerStrapGuide: 229 case ControllerSupportMode::ShowControllerStrapGuide:
212 case ControllerSupportMode::ShowControllerFirmwareUpdate: 230 case ControllerSupportMode::ShowControllerFirmwareUpdate:
231 case ControllerSupportMode::ShowControllerKeyRemappingForSystem:
213 UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented", 232 UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented",
214 controller_private_arg.mode); 233 controller_private_arg.mode);
215 ConfigurationComplete(); 234 ConfigurationComplete();
diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h
index 20617e91f..0a34c4fc0 100644
--- a/src/core/hle/service/am/applets/applet_controller.h
+++ b/src/core/hle/service/am/applets/applet_controller.h
@@ -25,13 +25,15 @@ enum class ControllerAppletVersion : u32_le {
25 Version3 = 0x3, // 1.0.0 - 2.3.0 25 Version3 = 0x3, // 1.0.0 - 2.3.0
26 Version4 = 0x4, // 3.0.0 - 5.1.0 26 Version4 = 0x4, // 3.0.0 - 5.1.0
27 Version5 = 0x5, // 6.0.0 - 7.0.1 27 Version5 = 0x5, // 6.0.0 - 7.0.1
28 Version7 = 0x7, // 8.0.0+ 28 Version7 = 0x7, // 8.0.0 - 10.2.0
29 Version8 = 0x8, // 11.0.0+
29}; 30};
30 31
31enum class ControllerSupportMode : u8 { 32enum class ControllerSupportMode : u8 {
32 ShowControllerSupport, 33 ShowControllerSupport,
33 ShowControllerStrapGuide, 34 ShowControllerStrapGuide,
34 ShowControllerFirmwareUpdate, 35 ShowControllerFirmwareUpdate,
36 ShowControllerKeyRemappingForSystem,
35 37
36 MaxControllerSupportMode, 38 MaxControllerSupportMode,
37}; 39};
@@ -78,7 +80,7 @@ struct ControllerSupportArgOld {
78static_assert(sizeof(ControllerSupportArgOld) == 0x21C, 80static_assert(sizeof(ControllerSupportArgOld) == 0x21C,
79 "ControllerSupportArgOld has incorrect size."); 81 "ControllerSupportArgOld has incorrect size.");
80 82
81// LibraryAppletVersion 0x7 83// LibraryAppletVersion 0x7, 0x8
82struct ControllerSupportArgNew { 84struct ControllerSupportArgNew {
83 ControllerSupportArgHeader header{}; 85 ControllerSupportArgHeader header{};
84 std::array<IdentificationColor, 8> identification_colors{}; 86 std::array<IdentificationColor, 8> identification_colors{};
@@ -95,6 +97,14 @@ struct ControllerUpdateFirmwareArg {
95static_assert(sizeof(ControllerUpdateFirmwareArg) == 0x4, 97static_assert(sizeof(ControllerUpdateFirmwareArg) == 0x4,
96 "ControllerUpdateFirmwareArg has incorrect size."); 98 "ControllerUpdateFirmwareArg has incorrect size.");
97 99
100struct ControllerKeyRemappingArg {
101 u64 unknown{};
102 u32 unknown_2{};
103 INSERT_PADDING_WORDS(1);
104};
105static_assert(sizeof(ControllerKeyRemappingArg) == 0x10,
106 "ControllerKeyRemappingArg has incorrect size.");
107
98struct ControllerSupportResultInfo { 108struct ControllerSupportResultInfo {
99 s8 player_count{}; 109 s8 player_count{};
100 INSERT_PADDING_BYTES(3); 110 INSERT_PADDING_BYTES(3);
@@ -128,6 +138,7 @@ private:
128 ControllerSupportArgOld controller_user_arg_old; 138 ControllerSupportArgOld controller_user_arg_old;
129 ControllerSupportArgNew controller_user_arg_new; 139 ControllerSupportArgNew controller_user_arg_new;
130 ControllerUpdateFirmwareArg controller_update_arg; 140 ControllerUpdateFirmwareArg controller_update_arg;
141 ControllerKeyRemappingArg controller_key_remapping_arg;
131 bool complete{false}; 142 bool complete{false};
132 ResultCode status{ResultSuccess}; 143 ResultCode status{ResultSuccess};
133 bool is_single_mode{false}; 144 bool is_single_mode{false};
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 7778b3562..70a0ba09c 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -707,7 +707,8 @@ public:
707 707
708 if (params.Has("axis")) { 708 if (params.Has("axis")) {
709 const int axis = params.Get("axis", 0); 709 const int axis = params.Get("axis", 0);
710 const float threshold = params.Get("threshold", 0.5f); 710 // Convert range from (0.0, 1.0) to (-1.0, 1.0)
711 const float threshold = (params.Get("threshold", 0.5f) - 0.5f) * 2.0f;
711 const std::string direction_name = params.Get("direction", ""); 712 const std::string direction_name = params.Get("direction", "");
712 bool trigger_if_greater; 713 bool trigger_if_greater;
713 if (direction_name == "+") { 714 if (direction_name == "+") {
@@ -980,12 +981,11 @@ Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid
980 params.Set("port", port); 981 params.Set("port", port);
981 params.Set("guid", std::move(guid)); 982 params.Set("guid", std::move(guid));
982 params.Set("axis", axis); 983 params.Set("axis", axis);
984 params.Set("threshold", "0.5");
983 if (value > 0) { 985 if (value > 0) {
984 params.Set("direction", "+"); 986 params.Set("direction", "+");
985 params.Set("threshold", "0.5");
986 } else { 987 } else {
987 params.Set("direction", "-"); 988 params.Set("direction", "-");
988 params.Set("threshold", "-0.5");
989 } 989 }
990 return params; 990 return params;
991} 991}
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index fd01c902c..88ccf96f5 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -765,7 +765,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
765 dst_range.AddLayers(copy.dstSubresource); 765 dst_range.AddLayers(copy.dstSubresource);
766 src_range.AddLayers(copy.srcSubresource); 766 src_range.AddLayers(copy.srcSubresource);
767 } 767 }
768 const std::array read_barriers{ 768 const std::array pre_barriers{
769 VkImageMemoryBarrier{ 769 VkImageMemoryBarrier{
770 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 770 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
771 .pNext = nullptr, 771 .pNext = nullptr,
@@ -774,7 +774,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
774 VK_ACCESS_TRANSFER_WRITE_BIT, 774 VK_ACCESS_TRANSFER_WRITE_BIT,
775 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, 775 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
776 .oldLayout = VK_IMAGE_LAYOUT_GENERAL, 776 .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
777 .newLayout = VK_IMAGE_LAYOUT_GENERAL, 777 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
778 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 778 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
779 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 779 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
780 .image = src_image, 780 .image = src_image,
@@ -795,29 +795,43 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
795 .subresourceRange = dst_range.SubresourceRange(aspect_mask), 795 .subresourceRange = dst_range.SubresourceRange(aspect_mask),
796 }, 796 },
797 }; 797 };
798 const VkImageMemoryBarrier write_barrier{ 798 const std::array post_barriers{
799 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 799 VkImageMemoryBarrier{
800 .pNext = nullptr, 800 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
801 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, 801 .pNext = nullptr,
802 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | 802 .srcAccessMask = 0,
803 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 803 .dstAccessMask = 0,
804 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 804 .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
805 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | 805 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
806 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 806 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
807 VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, 807 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
808 .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 808 .image = src_image,
809 .newLayout = VK_IMAGE_LAYOUT_GENERAL, 809 .subresourceRange = src_range.SubresourceRange(aspect_mask),
810 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 810 },
811 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 811 VkImageMemoryBarrier{
812 .image = dst_image, 812 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
813 .subresourceRange = dst_range.SubresourceRange(aspect_mask), 813 .pNext = nullptr,
814 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
815 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
816 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
817 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
818 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
819 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
820 VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
821 .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
822 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
823 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
824 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
825 .image = dst_image,
826 .subresourceRange = dst_range.SubresourceRange(aspect_mask),
827 },
814 }; 828 };
815 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 829 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
816 0, {}, {}, read_barriers); 830 0, {}, {}, pre_barriers);
817 cmdbuf.CopyImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, 831 cmdbuf.CopyImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image,
818 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk_copies); 832 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk_copies);
819 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 833 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
820 0, write_barrier); 834 0, {}, {}, post_barriers);
821 }); 835 });
822} 836}
823 837
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 14579c220..6b9bd05f1 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -314,6 +314,24 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
314 buttons_param[button_id].Set("toggle", toggle_value); 314 buttons_param[button_id].Set("toggle", toggle_value);
315 button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); 315 button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
316 }); 316 });
317 if (buttons_param[button_id].Has("threshold")) {
318 context_menu.addAction(tr("Set threshold"), [&] {
319 const int button_threshold = static_cast<int>(
320 buttons_param[button_id].Get("threshold", 0.5f) * 100.0f);
321 const int new_threshold = QInputDialog::getInt(
322 this, tr("Set threshold"), tr("Choose a value between 0% and 100%"),
323 button_threshold, 0, 100);
324 buttons_param[button_id].Set("threshold", new_threshold / 100.0f);
325
326 if (button_id == Settings::NativeButton::ZL) {
327 ui->sliderZLThreshold->setValue(new_threshold);
328 }
329 if (button_id == Settings::NativeButton::ZR) {
330 ui->sliderZRThreshold->setValue(new_threshold);
331 }
332 });
333 }
334
317 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); 335 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
318 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); 336 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
319 }); 337 });
@@ -342,6 +360,20 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
342 }); 360 });
343 } 361 }
344 362
363 connect(ui->sliderZLThreshold, &QSlider::valueChanged, [=, this] {
364 if (buttons_param[Settings::NativeButton::ZL].Has("threshold")) {
365 const auto slider_value = ui->sliderZLThreshold->value();
366 buttons_param[Settings::NativeButton::ZL].Set("threshold", slider_value / 100.0f);
367 }
368 });
369
370 connect(ui->sliderZRThreshold, &QSlider::valueChanged, [=, this] {
371 if (buttons_param[Settings::NativeButton::ZR].Has("threshold")) {
372 const auto slider_value = ui->sliderZRThreshold->value();
373 buttons_param[Settings::NativeButton::ZR].Set("threshold", slider_value / 100.0f);
374 }
375 });
376
345 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { 377 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
346 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { 378 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
347 auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; 379 auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
@@ -850,6 +882,18 @@ void ConfigureInputPlayer::UpdateUI() {
850 button_map[button]->setText(ButtonToText(buttons_param[button])); 882 button_map[button]->setText(ButtonToText(buttons_param[button]));
851 } 883 }
852 884
885 if (buttons_param[Settings::NativeButton::ZL].Has("threshold")) {
886 const int button_threshold = static_cast<int>(
887 buttons_param[Settings::NativeButton::ZL].Get("threshold", 0.5f) * 100.0f);
888 ui->sliderZLThreshold->setValue(button_threshold);
889 }
890
891 if (buttons_param[Settings::NativeButton::ZR].Has("threshold")) {
892 const int button_threshold = static_cast<int>(
893 buttons_param[Settings::NativeButton::ZR].Get("threshold", 0.5f) * 100.0f);
894 ui->sliderZRThreshold->setValue(button_threshold);
895 }
896
853 for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { 897 for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
854 motion_map[motion_id]->setText(ButtonToText(motions_param[motion_id])); 898 motion_map[motion_id]->setText(ButtonToText(motions_param[motion_id]));
855 } 899 }
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index e76aa484f..e7433912b 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -1334,6 +1334,12 @@
1334 </item> 1334 </item>
1335 <item> 1335 <item>
1336 <widget class="QGroupBox" name="buttonShoulderButtonsButtonZLGroup"> 1336 <widget class="QGroupBox" name="buttonShoulderButtonsButtonZLGroup">
1337 <property name="sizePolicy">
1338 <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
1339 <horstretch>0</horstretch>
1340 <verstretch>0</verstretch>
1341 </sizepolicy>
1342 </property>
1337 <property name="title"> 1343 <property name="title">
1338 <string>ZL</string> 1344 <string>ZL</string>
1339 </property> 1345 </property>
@@ -1378,6 +1384,22 @@
1378 </property> 1384 </property>
1379 </widget> 1385 </widget>
1380 </item> 1386 </item>
1387 <item>
1388 <widget class="QSlider" name="sliderZLThreshold">
1389 <property name="maximumSize">
1390 <size>
1391 <width>70</width>
1392 <height>15</height>
1393 </size>
1394 </property>
1395 <property name="maximum">
1396 <number>100</number>
1397 </property>
1398 <property name="orientation">
1399 <enum>Qt::Horizontal</enum>
1400 </property>
1401 </widget>
1402 </item>
1381 </layout> 1403 </layout>
1382 </widget> 1404 </widget>
1383 </item> 1405 </item>
@@ -1759,6 +1781,12 @@
1759 </item> 1781 </item>
1760 <item> 1782 <item>
1761 <widget class="QGroupBox" name="buttonShoulderButtonsZRGroup"> 1783 <widget class="QGroupBox" name="buttonShoulderButtonsZRGroup">
1784 <property name="sizePolicy">
1785 <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
1786 <horstretch>0</horstretch>
1787 <verstretch>0</verstretch>
1788 </sizepolicy>
1789 </property>
1762 <property name="title"> 1790 <property name="title">
1763 <string>ZR</string> 1791 <string>ZR</string>
1764 </property> 1792 </property>
@@ -1803,6 +1831,22 @@
1803 </property> 1831 </property>
1804 </widget> 1832 </widget>
1805 </item> 1833 </item>
1834 <item>
1835 <widget class="QSlider" name="sliderZRThreshold">
1836 <property name="maximumSize">
1837 <size>
1838 <width>70</width>
1839 <height>15</height>
1840 </size>
1841 </property>
1842 <property name="maximum">
1843 <number>100</number>
1844 </property>
1845 <property name="orientation">
1846 <enum>Qt::Horizontal</enum>
1847 </property>
1848 </widget>
1849 </item>
1806 </layout> 1850 </layout>
1807 </widget> 1851 </widget>
1808 </item> 1852 </item>
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index b18056baf..3e22fee37 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -446,6 +446,7 @@ void Config::ReadValues() {
446 ReadSetting("Renderer", Settings::values.renderer_debug); 446 ReadSetting("Renderer", Settings::values.renderer_debug);
447 ReadSetting("Renderer", Settings::values.vulkan_device); 447 ReadSetting("Renderer", Settings::values.vulkan_device);
448 448
449 ReadSetting("Renderer", Settings::values.fullscreen_mode);
449 ReadSetting("Renderer", Settings::values.aspect_ratio); 450 ReadSetting("Renderer", Settings::values.aspect_ratio);
450 ReadSetting("Renderer", Settings::values.max_anisotropy); 451 ReadSetting("Renderer", Settings::values.max_anisotropy);
451 ReadSetting("Renderer", Settings::values.use_frame_limit); 452 ReadSetting("Renderer", Settings::values.use_frame_limit);
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index b362f10b4..88d33ecab 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -224,6 +224,10 @@ debug =
224# Which Vulkan physical device to use (defaults to 0) 224# Which Vulkan physical device to use (defaults to 0)
225vulkan_device = 225vulkan_device =
226 226
227# Whether to use fullscreen or borderless window mode
228# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen
229fullscreen_mode =
230
227# Aspect ratio 231# Aspect ratio
228# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Stretch to Window 232# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Stretch to Window
229aspect_ratio = 233aspect_ratio =
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 896181f0b..353e51ea7 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -6,6 +6,7 @@
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "common/scm_rev.h" 8#include "common/scm_rev.h"
9#include "common/settings.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/perf_stats.h" 11#include "core/perf_stats.h"
11#include "input_common/keyboard.h" 12#include "input_common/keyboard.h"
@@ -122,24 +123,37 @@ void EmuWindow_SDL2::OnResize() {
122} 123}
123 124
124void EmuWindow_SDL2::Fullscreen() { 125void EmuWindow_SDL2::Fullscreen() {
125 if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN) == 0) { 126 switch (Settings::values.fullscreen_mode.GetValue()) {
126 return; 127 case 1: // Exclusive fullscreen
127 } 128 // Set window size to render size before entering fullscreen -- SDL does not resize to
128 129 // display dimensions in this mode.
129 LOG_ERROR(Frontend, "Fullscreening failed: {}", SDL_GetError()); 130 // TODO: Multiply the window size by resolution_factor (for both docked modes)
131 if (Settings::values.use_docked_mode) {
132 SDL_SetWindowSize(render_window, Layout::ScreenDocked::Width,
133 Layout::ScreenDocked::Height);
134 }
130 135
131 // Try a different fullscreening method 136 if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN) == 0) {
132 LOG_INFO(Frontend, "Attempting to use borderless fullscreen..."); 137 return;
133 if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) { 138 }
134 return;
135 }
136 139
137 LOG_ERROR(Frontend, "Borderless fullscreening failed: {}", SDL_GetError()); 140 LOG_ERROR(Frontend, "Fullscreening failed: {}", SDL_GetError());
141 LOG_INFO(Frontend, "Attempting to use borderless fullscreen...");
142 [[fallthrough]];
143 case 0: // Borderless window
144 if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) {
145 return;
146 }
138 147
139 // Fallback algorithm: Maximise window. 148 LOG_ERROR(Frontend, "Borderless fullscreening failed: {}", SDL_GetError());
140 // Works on all systems (unless something is seriously wrong), so no fallback for this one. 149 [[fallthrough]];
141 LOG_INFO(Frontend, "Falling back on a maximised window..."); 150 default:
142 SDL_MaximizeWindow(render_window); 151 // Fallback algorithm: Maximise window.
152 // Works on all systems (unless something is seriously wrong), so no fallback for this one.
153 LOG_INFO(Frontend, "Falling back on a maximised window...");
154 SDL_MaximizeWindow(render_window);
155 break;
156 }
143} 157}
144 158
145void EmuWindow_SDL2::WaitEvent() { 159void EmuWindow_SDL2::WaitEvent() {
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index 152e56db8..d1473dbab 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -24,7 +24,7 @@
24#include <SDL.h> 24#include <SDL.h>
25#include <SDL_syswm.h> 25#include <SDL_syswm.h>
26 26
27EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem) 27EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, bool fullscreen)
28 : EmuWindow_SDL2{input_subsystem} { 28 : EmuWindow_SDL2{input_subsystem} {
29 const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, 29 const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name,
30 Common::g_scm_branch, Common::g_scm_desc); 30 Common::g_scm_branch, Common::g_scm_desc);
@@ -42,6 +42,10 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste
42 42
43 SetWindowIcon(); 43 SetWindowIcon();
44 44
45 if (fullscreen) {
46 Fullscreen();
47 }
48
45 switch (wm.subsystem) { 49 switch (wm.subsystem) {
46#ifdef SDL_VIDEO_DRIVER_WINDOWS 50#ifdef SDL_VIDEO_DRIVER_WINDOWS
47 case SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS: 51 case SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS:
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
index bdfdc3c6f..de53844f0 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
@@ -19,7 +19,7 @@ class InputSubsystem;
19 19
20class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { 20class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 {
21public: 21public:
22 explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem); 22 explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, bool fullscreen);
23 ~EmuWindow_SDL2_VK() override; 23 ~EmuWindow_SDL2_VK() override;
24 24
25 std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; 25 std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 9607cdcb1..ac4ea88d3 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -175,7 +175,7 @@ int main(int argc, char** argv) {
175 emu_window = std::make_unique<EmuWindow_SDL2_GL>(&input_subsystem, fullscreen); 175 emu_window = std::make_unique<EmuWindow_SDL2_GL>(&input_subsystem, fullscreen);
176 break; 176 break;
177 case Settings::RendererBackend::Vulkan: 177 case Settings::RendererBackend::Vulkan:
178 emu_window = std::make_unique<EmuWindow_SDL2_VK>(&input_subsystem); 178 emu_window = std::make_unique<EmuWindow_SDL2_VK>(&input_subsystem, fullscreen);
179 break; 179 break;
180 } 180 }
181 181