summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt6
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt5
-rw-r--r--src/android/app/src/main/jni/android_config.cpp2
-rw-r--r--src/core/hle/service/nfc/common/device.cpp5
-rw-r--r--src/frontend_common/config.cpp34
-rw-r--r--src/frontend_common/config.h1
-rw-r--r--src/input_common/CMakeLists.txt2
-rw-r--r--src/input_common/drivers/android.cpp48
-rw-r--r--src/input_common/drivers/android.h54
-rw-r--r--src/input_common/input_mapping.cpp3
-rw-r--r--src/input_common/main.cpp22
-rw-r--r--src/input_common/main.h7
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp76
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_instructions.h2
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp16
-rw-r--r--src/yuzu/configuration/input_profiles.cpp3
-rw-r--r--src/yuzu/configuration/qt_config.cpp7
-rw-r--r--src/yuzu_cmd/sdl_config.cpp4
18 files changed, 254 insertions, 43 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
index 93c8ce922..9b08f008d 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
@@ -49,7 +49,6 @@ import org.yuzu.yuzu_emu.utils.ForegroundService
49import org.yuzu.yuzu_emu.utils.InputHandler 49import org.yuzu.yuzu_emu.utils.InputHandler
50import org.yuzu.yuzu_emu.utils.Log 50import org.yuzu.yuzu_emu.utils.Log
51import org.yuzu.yuzu_emu.utils.MemoryUtil 51import org.yuzu.yuzu_emu.utils.MemoryUtil
52import org.yuzu.yuzu_emu.utils.NativeConfig
53import org.yuzu.yuzu_emu.utils.NfcReader 52import org.yuzu.yuzu_emu.utils.NfcReader
54import org.yuzu.yuzu_emu.utils.ThemeHelper 53import org.yuzu.yuzu_emu.utils.ThemeHelper
55import java.text.NumberFormat 54import java.text.NumberFormat
@@ -171,11 +170,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
171 stopMotionSensorListener() 170 stopMotionSensorListener()
172 } 171 }
173 172
174 override fun onStop() {
175 super.onStop()
176 NativeConfig.saveGlobalConfig()
177 }
178
179 override fun onUserLeaveHint() { 173 override fun onUserLeaveHint() {
180 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { 174 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
181 if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) { 175 if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 9efc1705d..47767454a 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -554,6 +554,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
554 findItem(R.id.menu_touchscreen).isChecked = BooleanSetting.TOUCHSCREEN.getBoolean() 554 findItem(R.id.menu_touchscreen).isChecked = BooleanSetting.TOUCHSCREEN.getBoolean()
555 } 555 }
556 556
557 popup.setOnDismissListener { NativeConfig.saveGlobalConfig() }
557 popup.setOnMenuItemClickListener { 558 popup.setOnMenuItemClickListener {
558 when (it.itemId) { 559 when (it.itemId) {
559 R.id.menu_toggle_fps -> { 560 R.id.menu_toggle_fps -> {
@@ -720,7 +721,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
720 MaterialAlertDialogBuilder(requireContext()) 721 MaterialAlertDialogBuilder(requireContext())
721 .setTitle(R.string.emulation_control_adjust) 722 .setTitle(R.string.emulation_control_adjust)
722 .setView(adjustBinding.root) 723 .setView(adjustBinding.root)
723 .setPositiveButton(android.R.string.ok, null) 724 .setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
725 NativeConfig.saveGlobalConfig()
726 }
724 .setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int -> 727 .setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int ->
725 setControlScale(50) 728 setControlScale(50)
726 setControlOpacity(100) 729 setControlOpacity(100)
diff --git a/src/android/app/src/main/jni/android_config.cpp b/src/android/app/src/main/jni/android_config.cpp
index 08aed3216..e147560c3 100644
--- a/src/android/app/src/main/jni/android_config.cpp
+++ b/src/android/app/src/main/jni/android_config.cpp
@@ -21,7 +21,7 @@ void AndroidConfig::ReloadAllValues() {
21} 21}
22 22
23void AndroidConfig::SaveAllValues() { 23void AndroidConfig::SaveAllValues() {
24 Save(); 24 SaveValues();
25 SaveAndroidValues(); 25 SaveAndroidValues();
26} 26}
27 27
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp
index 31cc87acc..cc7776efc 100644
--- a/src/core/hle/service/nfc/common/device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -441,7 +441,10 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target
441 device_state = DeviceState::TagMounted; 441 device_state = DeviceState::TagMounted;
442 mount_target = mount_target_; 442 mount_target = mount_target_;
443 443
444 if (!is_corrupted && mount_target != NFP::MountTarget::Rom) { 444 const bool create_backup =
445 mount_target == NFP::MountTarget::All || mount_target == NFP::MountTarget::Ram ||
446 (mount_target == NFP::MountTarget::Rom && HasBackup(encrypted_tag_data.uuid).IsError());
447 if (!is_corrupted && create_backup) {
445 std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); 448 std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File));
446 memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); 449 memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data));
447 WriteBackupData(encrypted_tag_data.uuid, data); 450 WriteBackupData(encrypted_tag_data.uuid, data);
diff --git a/src/frontend_common/config.cpp b/src/frontend_common/config.cpp
index 9eb4799a6..46277e288 100644
--- a/src/frontend_common/config.cpp
+++ b/src/frontend_common/config.cpp
@@ -5,6 +5,7 @@
5#include <array> 5#include <array>
6#include "common/fs/fs.h" 6#include "common/fs/fs.h"
7#include "common/fs/path_util.h" 7#include "common/fs/path_util.h"
8#include "common/logging/log.h"
8#include "common/settings.h" 9#include "common/settings.h"
9#include "common/settings_common.h" 10#include "common/settings_common.h"
10#include "common/settings_enums.h" 11#include "common/settings_enums.h"
@@ -58,6 +59,19 @@ void Config::Initialize(const std::optional<std::string> config_path) {
58} 59}
59 60
60void Config::WriteToIni() const { 61void Config::WriteToIni() const {
62 std::string config_type;
63 switch (type) {
64 case ConfigType::GlobalConfig:
65 config_type = "Global";
66 break;
67 case ConfigType::PerGameConfig:
68 config_type = "Game Specific";
69 break;
70 case ConfigType::InputProfile:
71 config_type = "Input Profile";
72 break;
73 }
74 LOG_INFO(Config, "Writing {} configuration to: {}", config_type, config_loc);
61 FILE* fp = nullptr; 75 FILE* fp = nullptr;
62#ifdef _WIN32 76#ifdef _WIN32
63 fp = _wfopen(Common::UTF8ToUTF16W(config_loc).data(), L"wb"); 77 fp = _wfopen(Common::UTF8ToUTF16W(config_loc).data(), L"wb");
@@ -117,10 +131,10 @@ void Config::ReadPlayerValues(const std::size_t player_index) {
117 player_prefix.append("player_").append(ToString(player_index)).append("_"); 131 player_prefix.append("player_").append(ToString(player_index)).append("_");
118 } 132 }
119 133
134 const auto profile_name = ReadStringSetting(std::string(player_prefix).append("profile_name"));
135
120 auto& player = Settings::values.players.GetValue()[player_index]; 136 auto& player = Settings::values.players.GetValue()[player_index];
121 if (IsCustomConfig()) { 137 if (IsCustomConfig()) {
122 const auto profile_name =
123 ReadStringSetting(std::string(player_prefix).append("profile_name"));
124 if (profile_name.empty()) { 138 if (profile_name.empty()) {
125 // Use the global input config 139 // Use the global input config
126 player = Settings::values.players.GetValue(true)[player_index]; 140 player = Settings::values.players.GetValue(true)[player_index];
@@ -139,6 +153,10 @@ void Config::ReadPlayerValues(const std::size_t player_index) {
139 player.controller_type = controller; 153 player.controller_type = controller;
140 } 154 }
141 } else { 155 } else {
156 if (global) {
157 auto& player_global = Settings::values.players.GetValue(true)[player_index];
158 player_global.profile_name = profile_name;
159 }
142 std::string connected_key = player_prefix; 160 std::string connected_key = player_prefix;
143 player.connected = ReadBooleanSetting(connected_key.append("connected"), 161 player.connected = ReadBooleanSetting(connected_key.append("connected"),
144 std::make_optional(player_index == 0)); 162 std::make_optional(player_index == 0));
@@ -412,6 +430,11 @@ void Config::SavePlayerValues(const std::size_t player_index) {
412 std::make_optional(static_cast<u8>(Settings::ControllerType::ProController))); 430 std::make_optional(static_cast<u8>(Settings::ControllerType::ProController)));
413 431
414 if (!player_prefix.empty() || !Settings::IsConfiguringGlobal()) { 432 if (!player_prefix.empty() || !Settings::IsConfiguringGlobal()) {
433 if (global) {
434 const auto& player_global = Settings::values.players.GetValue(true)[player_index];
435 WriteStringSetting(std::string(player_prefix).append("profile_name"),
436 player_global.profile_name, std::make_optional(std::string("")));
437 }
415 WriteBooleanSetting(std::string(player_prefix).append("connected"), player.connected, 438 WriteBooleanSetting(std::string(player_prefix).append("connected"), player.connected,
416 std::make_optional(player_index == 0)); 439 std::make_optional(player_index == 0));
417 WriteIntegerSetting(std::string(player_prefix).append("vibration_enabled"), 440 WriteIntegerSetting(std::string(player_prefix).append("vibration_enabled"),
@@ -468,12 +491,15 @@ void Config::SaveMotionTouchValues() {
468 491
469void Config::SaveValues() { 492void Config::SaveValues() {
470 if (global) { 493 if (global) {
494 LOG_DEBUG(Config, "Saving global generic configuration values");
471 SaveDataStorageValues(); 495 SaveDataStorageValues();
472 SaveDebuggingValues(); 496 SaveDebuggingValues();
473 SaveDisabledAddOnValues(); 497 SaveDisabledAddOnValues();
474 SaveNetworkValues(); 498 SaveNetworkValues();
475 SaveWebServiceValues(); 499 SaveWebServiceValues();
476 SaveMiscellaneousValues(); 500 SaveMiscellaneousValues();
501 } else {
502 LOG_DEBUG(Config, "Saving only generic configuration values");
477 } 503 }
478 SaveControlValues(); 504 SaveControlValues();
479 SaveCoreValues(); 505 SaveCoreValues();
@@ -814,10 +840,6 @@ void Config::Reload() {
814 SaveValues(); 840 SaveValues();
815} 841}
816 842
817void Config::Save() {
818 SaveValues();
819}
820
821void Config::ClearControlPlayerValues() const { 843void Config::ClearControlPlayerValues() const {
822 // If key is an empty string, all keys in the current group() are removed. 844 // If key is an empty string, all keys in the current group() are removed.
823 const char* section = Settings::TranslateCategory(Settings::Category::Controls); 845 const char* section = Settings::TranslateCategory(Settings::Category::Controls);
diff --git a/src/frontend_common/config.h b/src/frontend_common/config.h
index b01631649..4798d6432 100644
--- a/src/frontend_common/config.h
+++ b/src/frontend_common/config.h
@@ -51,7 +51,6 @@ protected:
51 [[nodiscard]] bool IsCustomConfig() const; 51 [[nodiscard]] bool IsCustomConfig() const;
52 52
53 void Reload(); 53 void Reload();
54 void Save();
55 54
56 /** 55 /**
57 * Derived config classes must implement this so they can reload all platform-specific 56 * Derived config classes must implement this so they can reload all platform-specific
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index d2fbea488..d0a71a15b 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -2,6 +2,8 @@
2# SPDX-License-Identifier: GPL-2.0-or-later 2# SPDX-License-Identifier: GPL-2.0-or-later
3 3
4add_library(input_common STATIC 4add_library(input_common STATIC
5 drivers/android.cpp
6 drivers/android.h
5 drivers/camera.cpp 7 drivers/camera.cpp
6 drivers/camera.h 8 drivers/camera.h
7 drivers/keyboard.cpp 9 drivers/keyboard.cpp
diff --git a/src/input_common/drivers/android.cpp b/src/input_common/drivers/android.cpp
new file mode 100644
index 000000000..b6a03fdc0
--- /dev/null
+++ b/src/input_common/drivers/android.cpp
@@ -0,0 +1,48 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "input_common/drivers/android.h"
5
6namespace InputCommon {
7
8Android::Android(std::string input_engine_) : InputEngine(std::move(input_engine_)) {}
9
10void Android::RegisterController(std::size_t controller_number) {
11 PreSetController(GetIdentifier(controller_number));
12}
13
14void Android::SetButtonState(std::size_t controller_number, int button_id, bool value) {
15 const auto identifier = GetIdentifier(controller_number);
16 SetButton(identifier, button_id, value);
17}
18
19void Android::SetAxisState(std::size_t controller_number, int axis_id, float value) {
20 const auto identifier = GetIdentifier(controller_number);
21 SetAxis(identifier, axis_id, value);
22}
23
24void Android::SetMotionState(std::size_t controller_number, u64 delta_timestamp, float gyro_x,
25 float gyro_y, float gyro_z, float accel_x, float accel_y,
26 float accel_z) {
27 const auto identifier = GetIdentifier(controller_number);
28 const BasicMotion motion_data{
29 .gyro_x = gyro_x,
30 .gyro_y = gyro_y,
31 .gyro_z = gyro_z,
32 .accel_x = accel_x,
33 .accel_y = accel_y,
34 .accel_z = accel_z,
35 .delta_timestamp = delta_timestamp,
36 };
37 SetMotion(identifier, 0, motion_data);
38}
39
40PadIdentifier Android::GetIdentifier(std::size_t controller_number) const {
41 return {
42 .guid = Common::UUID{},
43 .port = controller_number,
44 .pad = 0,
45 };
46}
47
48} // namespace InputCommon
diff --git a/src/input_common/drivers/android.h b/src/input_common/drivers/android.h
new file mode 100644
index 000000000..3f01817f6
--- /dev/null
+++ b/src/input_common/drivers/android.h
@@ -0,0 +1,54 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "input_common/input_engine.h"
7
8namespace InputCommon {
9
10/**
11 * A virtual controller that is always assigned to the game input
12 */
13class Android final : public InputEngine {
14public:
15 explicit Android(std::string input_engine_);
16
17 /**
18 * Registers controller number to accept new inputs
19 * @param controller_number the controller number that will take this action
20 */
21 void RegisterController(std::size_t controller_number);
22
23 /**
24 * Sets the status of all buttons bound with the key to pressed
25 * @param controller_number the controller number that will take this action
26 * @param button_id the id of the button
27 * @param value indicates if the button is pressed or not
28 */
29 void SetButtonState(std::size_t controller_number, int button_id, bool value);
30
31 /**
32 * Sets the status of a analog input to a specific player index
33 * @param controller_number the controller number that will take this action
34 * @param axis_id the id of the axis to move
35 * @param value the analog position of the axis
36 */
37 void SetAxisState(std::size_t controller_number, int axis_id, float value);
38
39 /**
40 * Sets the status of the motion sensor to a specific player index
41 * @param controller_number the controller number that will take this action
42 * @param delta_timestamp time passed since last reading
43 * @param gyro_x,gyro_y,gyro_z the gyro sensor readings
44 * @param accel_x,accel_y,accel_z the accelerometer reading
45 */
46 void SetMotionState(std::size_t controller_number, u64 delta_timestamp, float gyro_x,
47 float gyro_y, float gyro_z, float accel_x, float accel_y, float accel_z);
48
49private:
50 /// Returns the correct identifier corresponding to the player index
51 PadIdentifier GetIdentifier(std::size_t controller_number) const;
52};
53
54} // namespace InputCommon
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp
index 8c2ee4eb3..f1a1d7398 100644
--- a/src/input_common/input_mapping.cpp
+++ b/src/input_common/input_mapping.cpp
@@ -210,6 +210,9 @@ bool MappingFactory::IsDriverValid(const MappingData& data) const {
210 if (data.engine == "analog_from_button") { 210 if (data.engine == "analog_from_button") {
211 return false; 211 return false;
212 } 212 }
213 if (data.engine == "virtual_gamepad") {
214 return false;
215 }
213 return true; 216 return true;
214} 217}
215 218
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index c77fc04ee..f8749ebbf 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -4,6 +4,7 @@
4#include <memory> 4#include <memory>
5#include "common/input.h" 5#include "common/input.h"
6#include "common/param_package.h" 6#include "common/param_package.h"
7#include "input_common/drivers/android.h"
7#include "input_common/drivers/camera.h" 8#include "input_common/drivers/camera.h"
8#include "input_common/drivers/keyboard.h" 9#include "input_common/drivers/keyboard.h"
9#include "input_common/drivers/mouse.h" 10#include "input_common/drivers/mouse.h"
@@ -78,6 +79,7 @@ struct InputSubsystem::Impl {
78 RegisterEngine("cemuhookudp", udp_client); 79 RegisterEngine("cemuhookudp", udp_client);
79 RegisterEngine("tas", tas_input); 80 RegisterEngine("tas", tas_input);
80 RegisterEngine("camera", camera); 81 RegisterEngine("camera", camera);
82 RegisterEngine("android", android);
81 RegisterEngine("virtual_amiibo", virtual_amiibo); 83 RegisterEngine("virtual_amiibo", virtual_amiibo);
82 RegisterEngine("virtual_gamepad", virtual_gamepad); 84 RegisterEngine("virtual_gamepad", virtual_gamepad);
83#ifdef HAVE_SDL2 85#ifdef HAVE_SDL2
@@ -109,6 +111,7 @@ struct InputSubsystem::Impl {
109 UnregisterEngine(udp_client); 111 UnregisterEngine(udp_client);
110 UnregisterEngine(tas_input); 112 UnregisterEngine(tas_input);
111 UnregisterEngine(camera); 113 UnregisterEngine(camera);
114 UnregisterEngine(android);
112 UnregisterEngine(virtual_amiibo); 115 UnregisterEngine(virtual_amiibo);
113 UnregisterEngine(virtual_gamepad); 116 UnregisterEngine(virtual_gamepad);
114#ifdef HAVE_SDL2 117#ifdef HAVE_SDL2
@@ -129,6 +132,8 @@ struct InputSubsystem::Impl {
129 devices.insert(devices.end(), keyboard_devices.begin(), keyboard_devices.end()); 132 devices.insert(devices.end(), keyboard_devices.begin(), keyboard_devices.end());
130 auto mouse_devices = mouse->GetInputDevices(); 133 auto mouse_devices = mouse->GetInputDevices();
131 devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end()); 134 devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
135 auto android_devices = android->GetInputDevices();
136 devices.insert(devices.end(), android_devices.begin(), android_devices.end());
132#ifdef HAVE_LIBUSB 137#ifdef HAVE_LIBUSB
133 auto gcadapter_devices = gcadapter->GetInputDevices(); 138 auto gcadapter_devices = gcadapter->GetInputDevices();
134 devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end()); 139 devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end());
@@ -157,6 +162,9 @@ struct InputSubsystem::Impl {
157 if (engine == mouse->GetEngineName()) { 162 if (engine == mouse->GetEngineName()) {
158 return mouse; 163 return mouse;
159 } 164 }
165 if (engine == android->GetEngineName()) {
166 return android;
167 }
160#ifdef HAVE_LIBUSB 168#ifdef HAVE_LIBUSB
161 if (engine == gcadapter->GetEngineName()) { 169 if (engine == gcadapter->GetEngineName()) {
162 return gcadapter; 170 return gcadapter;
@@ -237,6 +245,9 @@ struct InputSubsystem::Impl {
237 if (engine == mouse->GetEngineName()) { 245 if (engine == mouse->GetEngineName()) {
238 return true; 246 return true;
239 } 247 }
248 if (engine == android->GetEngineName()) {
249 return true;
250 }
240#ifdef HAVE_LIBUSB 251#ifdef HAVE_LIBUSB
241 if (engine == gcadapter->GetEngineName()) { 252 if (engine == gcadapter->GetEngineName()) {
242 return true; 253 return true;
@@ -265,6 +276,7 @@ struct InputSubsystem::Impl {
265 void BeginConfiguration() { 276 void BeginConfiguration() {
266 keyboard->BeginConfiguration(); 277 keyboard->BeginConfiguration();
267 mouse->BeginConfiguration(); 278 mouse->BeginConfiguration();
279 android->BeginConfiguration();
268#ifdef HAVE_LIBUSB 280#ifdef HAVE_LIBUSB
269 gcadapter->BeginConfiguration(); 281 gcadapter->BeginConfiguration();
270#endif 282#endif
@@ -278,6 +290,7 @@ struct InputSubsystem::Impl {
278 void EndConfiguration() { 290 void EndConfiguration() {
279 keyboard->EndConfiguration(); 291 keyboard->EndConfiguration();
280 mouse->EndConfiguration(); 292 mouse->EndConfiguration();
293 android->EndConfiguration();
281#ifdef HAVE_LIBUSB 294#ifdef HAVE_LIBUSB
282 gcadapter->EndConfiguration(); 295 gcadapter->EndConfiguration();
283#endif 296#endif
@@ -308,6 +321,7 @@ struct InputSubsystem::Impl {
308 std::shared_ptr<TasInput::Tas> tas_input; 321 std::shared_ptr<TasInput::Tas> tas_input;
309 std::shared_ptr<CemuhookUDP::UDPClient> udp_client; 322 std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
310 std::shared_ptr<Camera> camera; 323 std::shared_ptr<Camera> camera;
324 std::shared_ptr<Android> android;
311 std::shared_ptr<VirtualAmiibo> virtual_amiibo; 325 std::shared_ptr<VirtualAmiibo> virtual_amiibo;
312 std::shared_ptr<VirtualGamepad> virtual_gamepad; 326 std::shared_ptr<VirtualGamepad> virtual_gamepad;
313 327
@@ -373,6 +387,14 @@ const Camera* InputSubsystem::GetCamera() const {
373 return impl->camera.get(); 387 return impl->camera.get();
374} 388}
375 389
390Android* InputSubsystem::GetAndroid() {
391 return impl->android.get();
392}
393
394const Android* InputSubsystem::GetAndroid() const {
395 return impl->android.get();
396}
397
376VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() { 398VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() {
377 return impl->virtual_amiibo.get(); 399 return impl->virtual_amiibo.get();
378} 400}
diff --git a/src/input_common/main.h b/src/input_common/main.h
index d64a6cb4c..1d19019ee 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -29,6 +29,7 @@ enum Values : int;
29} 29}
30 30
31namespace InputCommon { 31namespace InputCommon {
32class Android;
32class Camera; 33class Camera;
33class Keyboard; 34class Keyboard;
34class Mouse; 35class Mouse;
@@ -103,6 +104,12 @@ public:
103 /// Retrieves the underlying camera input device. 104 /// Retrieves the underlying camera input device.
104 [[nodiscard]] const Camera* GetCamera() const; 105 [[nodiscard]] const Camera* GetCamera() const;
105 106
107 /// Retrieves the underlying android input device.
108 [[nodiscard]] Android* GetAndroid();
109
110 /// Retrieves the underlying android input device.
111 [[nodiscard]] const Android* GetAndroid() const;
112
106 /// Retrieves the underlying virtual amiibo input device. 113 /// Retrieves the underlying virtual amiibo input device.
107 [[nodiscard]] VirtualAmiibo* GetVirtualAmiibo(); 114 [[nodiscard]] VirtualAmiibo* GetVirtualAmiibo();
108 115
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 800754554..64a4e0e55 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -12,6 +12,11 @@ namespace Shader::Backend::SPIRV {
12namespace { 12namespace {
13class ImageOperands { 13class ImageOperands {
14public: 14public:
15 [[maybe_unused]] static constexpr bool ImageSampleOffsetAllowed = false;
16 [[maybe_unused]] static constexpr bool ImageGatherOffsetAllowed = true;
17 [[maybe_unused]] static constexpr bool ImageFetchOffsetAllowed = false;
18 [[maybe_unused]] static constexpr bool ImageGradientOffsetAllowed = false;
19
15 explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp, 20 explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp,
16 Id lod, const IR::Value& offset) { 21 Id lod, const IR::Value& offset) {
17 if (has_bias) { 22 if (has_bias) {
@@ -22,7 +27,7 @@ public:
22 const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod}; 27 const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod};
23 Add(spv::ImageOperandsMask::Lod, lod_value); 28 Add(spv::ImageOperandsMask::Lod, lod_value);
24 } 29 }
25 AddOffset(ctx, offset); 30 AddOffset(ctx, offset, ImageSampleOffsetAllowed);
26 if (has_lod_clamp) { 31 if (has_lod_clamp) {
27 const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod}; 32 const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod};
28 Add(spv::ImageOperandsMask::MinLod, lod_clamp); 33 Add(spv::ImageOperandsMask::MinLod, lod_clamp);
@@ -55,20 +60,17 @@ public:
55 Add(spv::ImageOperandsMask::ConstOffsets, offsets); 60 Add(spv::ImageOperandsMask::ConstOffsets, offsets);
56 } 61 }
57 62
58 explicit ImageOperands(Id offset, Id lod, Id ms) { 63 explicit ImageOperands(Id lod, Id ms) {
59 if (Sirit::ValidId(lod)) { 64 if (Sirit::ValidId(lod)) {
60 Add(spv::ImageOperandsMask::Lod, lod); 65 Add(spv::ImageOperandsMask::Lod, lod);
61 } 66 }
62 if (Sirit::ValidId(offset)) {
63 Add(spv::ImageOperandsMask::Offset, offset);
64 }
65 if (Sirit::ValidId(ms)) { 67 if (Sirit::ValidId(ms)) {
66 Add(spv::ImageOperandsMask::Sample, ms); 68 Add(spv::ImageOperandsMask::Sample, ms);
67 } 69 }
68 } 70 }
69 71
70 explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives, 72 explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives,
71 u32 num_derivatives, Id offset, Id lod_clamp) { 73 u32 num_derivatives, const IR::Value& offset, Id lod_clamp) {
72 if (!Sirit::ValidId(derivatives)) { 74 if (!Sirit::ValidId(derivatives)) {
73 throw LogicError("Derivatives must be present"); 75 throw LogicError("Derivatives must be present");
74 } 76 }
@@ -83,16 +85,14 @@ public:
83 const Id derivatives_Y{ctx.OpCompositeConstruct( 85 const Id derivatives_Y{ctx.OpCompositeConstruct(
84 ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; 86 ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})};
85 Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y); 87 Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y);
86 if (Sirit::ValidId(offset)) { 88 AddOffset(ctx, offset, ImageGradientOffsetAllowed);
87 Add(spv::ImageOperandsMask::Offset, offset);
88 }
89 if (has_lod_clamp) { 89 if (has_lod_clamp) {
90 Add(spv::ImageOperandsMask::MinLod, lod_clamp); 90 Add(spv::ImageOperandsMask::MinLod, lod_clamp);
91 } 91 }
92 } 92 }
93 93
94 explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2, 94 explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2,
95 Id offset, Id lod_clamp) { 95 const IR::Value& offset, Id lod_clamp) {
96 if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) { 96 if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) {
97 throw LogicError("Derivatives must be present"); 97 throw LogicError("Derivatives must be present");
98 } 98 }
@@ -111,9 +111,7 @@ public:
111 const Id derivatives_id2{ctx.OpCompositeConstruct( 111 const Id derivatives_id2{ctx.OpCompositeConstruct(
112 ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})}; 112 ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})};
113 Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2); 113 Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2);
114 if (Sirit::ValidId(offset)) { 114 AddOffset(ctx, offset, ImageGradientOffsetAllowed);
115 Add(spv::ImageOperandsMask::Offset, offset);
116 }
117 if (has_lod_clamp) { 115 if (has_lod_clamp) {
118 Add(spv::ImageOperandsMask::MinLod, lod_clamp); 116 Add(spv::ImageOperandsMask::MinLod, lod_clamp);
119 } 117 }
@@ -132,7 +130,7 @@ public:
132 } 130 }
133 131
134private: 132private:
135 void AddOffset(EmitContext& ctx, const IR::Value& offset) { 133 void AddOffset(EmitContext& ctx, const IR::Value& offset, bool runtime_offset_allowed) {
136 if (offset.IsEmpty()) { 134 if (offset.IsEmpty()) {
137 return; 135 return;
138 } 136 }
@@ -165,7 +163,9 @@ private:
165 break; 163 break;
166 } 164 }
167 } 165 }
168 Add(spv::ImageOperandsMask::Offset, ctx.Def(offset)); 166 if (runtime_offset_allowed) {
167 Add(spv::ImageOperandsMask::Offset, ctx.Def(offset));
168 }
169 } 169 }
170 170
171 void Add(spv::ImageOperandsMask new_mask, Id value) { 171 void Add(spv::ImageOperandsMask new_mask, Id value) {
@@ -311,6 +311,37 @@ Id ImageGatherSubpixelOffset(EmitContext& ctx, const IR::TextureInstInfo& info,
311 return coords; 311 return coords;
312 } 312 }
313} 313}
314
315void AddOffsetToCoordinates(EmitContext& ctx, const IR::TextureInstInfo& info, Id& coords,
316 Id offset) {
317 if (!Sirit::ValidId(offset)) {
318 return;
319 }
320
321 Id result_type{};
322 switch (info.type) {
323 case TextureType::Buffer:
324 case TextureType::Color1D:
325 case TextureType::ColorArray1D: {
326 result_type = ctx.U32[1];
327 break;
328 }
329 case TextureType::Color2D:
330 case TextureType::Color2DRect:
331 case TextureType::ColorArray2D: {
332 result_type = ctx.U32[2];
333 break;
334 }
335 case TextureType::Color3D: {
336 result_type = ctx.U32[3];
337 break;
338 }
339 case TextureType::ColorCube:
340 case TextureType::ColorArrayCube:
341 return;
342 }
343 coords = ctx.OpIAdd(result_type, coords, offset);
344}
314} // Anonymous namespace 345} // Anonymous namespace
315 346
316Id EmitBindlessImageSampleImplicitLod(EmitContext&) { 347Id EmitBindlessImageSampleImplicitLod(EmitContext&) {
@@ -496,6 +527,7 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
496Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, 527Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
497 Id lod, Id ms) { 528 Id lod, Id ms) {
498 const auto info{inst->Flags<IR::TextureInstInfo>()}; 529 const auto info{inst->Flags<IR::TextureInstInfo>()};
530 AddOffsetToCoordinates(ctx, info, coords, offset);
499 if (info.type == TextureType::Buffer) { 531 if (info.type == TextureType::Buffer) {
500 lod = Id{}; 532 lod = Id{};
501 } 533 }
@@ -503,7 +535,7 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
503 // This image is multisampled, lod must be implicit 535 // This image is multisampled, lod must be implicit
504 lod = Id{}; 536 lod = Id{};
505 } 537 }
506 const ImageOperands operands(offset, lod, ms); 538 const ImageOperands operands(lod, ms);
507 return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], 539 return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],
508 TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); 540 TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
509} 541}
@@ -548,13 +580,13 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I
548} 580}
549 581
550Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 582Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
551 Id derivatives, Id offset, Id lod_clamp) { 583 Id derivatives, const IR::Value& offset, Id lod_clamp) {
552 const auto info{inst->Flags<IR::TextureInstInfo>()}; 584 const auto info{inst->Flags<IR::TextureInstInfo>()};
553 const auto operands = 585 const auto operands = info.num_derivatives == 3
554 info.num_derivatives == 3 586 ? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
555 ? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, offset, {}, lod_clamp) 587 ctx.Def(offset), {}, lod_clamp)
556 : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, info.num_derivatives, offset, 588 : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
557 lod_clamp); 589 info.num_derivatives, offset, lod_clamp);
558 return Emit(&EmitContext::OpImageSparseSampleExplicitLod, 590 return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
559 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], 591 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
560 Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); 592 Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
index 7d34575c8..5c01b1012 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
@@ -543,7 +543,7 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i
543 const IR::Value& skip_mips); 543 const IR::Value& skip_mips);
544Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); 544Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
545Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 545Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
546 Id derivatives, Id offset, Id lod_clamp); 546 Id derivatives, const IR::Value& offset, Id lod_clamp);
547Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); 547Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
548void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); 548void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color);
549Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index); 549Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index);
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 5dac9f1e7..400917f9d 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -1650,9 +1650,21 @@ void ConfigureInputPlayer::SaveProfile() {
1650void ConfigureInputPlayer::UpdateInputProfiles() { 1650void ConfigureInputPlayer::UpdateInputProfiles() {
1651 ui->comboProfiles->clear(); 1651 ui->comboProfiles->clear();
1652 1652
1653 for (const auto& profile_name : profiles->GetInputProfileNames()) { 1653 // Set current profile as empty by default
1654 int profile_index = -1;
1655
1656 // Add every available profile and search the player profile to set it as current one
1657 auto& current_profile = Settings::values.players.GetValue()[player_index].profile_name;
1658 std::vector<std::string> profile_names = profiles->GetInputProfileNames();
1659 std::string profile_name;
1660 for (size_t i = 0; i < profile_names.size(); i++) {
1661 profile_name = profile_names[i];
1654 ui->comboProfiles->addItem(QString::fromStdString(profile_name)); 1662 ui->comboProfiles->addItem(QString::fromStdString(profile_name));
1663 if (current_profile == profile_name) {
1664 profile_index = (int)i;
1665 }
1655 } 1666 }
1656 1667
1657 ui->comboProfiles->setCurrentIndex(-1); 1668 LOG_DEBUG(Frontend, "Setting the current input profile to index {}", profile_index);
1669 ui->comboProfiles->setCurrentIndex(profile_index);
1658} 1670}
diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp
index 716efbccd..ebebadc94 100644
--- a/src/yuzu/configuration/input_profiles.cpp
+++ b/src/yuzu/configuration/input_profiles.cpp
@@ -5,6 +5,7 @@
5 5
6#include "common/fs/fs.h" 6#include "common/fs/fs.h"
7#include "common/fs/path_util.h" 7#include "common/fs/path_util.h"
8#include "common/logging/log.h"
8#include "frontend_common/config.h" 9#include "frontend_common/config.h"
9#include "yuzu/configuration/input_profiles.h" 10#include "yuzu/configuration/input_profiles.h"
10 11
@@ -113,6 +114,8 @@ bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t pla
113 return false; 114 return false;
114 } 115 }
115 116
117 LOG_INFO(Config, "Loading input profile `{}`", profile_name);
118
116 map_profiles[profile_name]->ReadQtControlPlayerValues(player_index); 119 map_profiles[profile_name]->ReadQtControlPlayerValues(player_index);
117 return true; 120 return true;
118} 121}
diff --git a/src/yuzu/configuration/qt_config.cpp b/src/yuzu/configuration/qt_config.cpp
index 6aca71d7c..1051031f2 100644
--- a/src/yuzu/configuration/qt_config.cpp
+++ b/src/yuzu/configuration/qt_config.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/logging/log.h"
4#include "input_common/main.h" 5#include "input_common/main.h"
5#include "qt_config.h" 6#include "qt_config.h"
6#include "uisettings.h" 7#include "uisettings.h"
@@ -65,7 +66,7 @@ void QtConfig::ReloadAllValues() {
65} 66}
66 67
67void QtConfig::SaveAllValues() { 68void QtConfig::SaveAllValues() {
68 Save(); 69 SaveValues();
69 SaveQtValues(); 70 SaveQtValues();
70} 71}
71 72
@@ -327,7 +328,10 @@ void QtConfig::ReadMultiplayerValues() {
327 328
328void QtConfig::SaveQtValues() { 329void QtConfig::SaveQtValues() {
329 if (global) { 330 if (global) {
331 LOG_DEBUG(Config, "Saving global Qt configuration values");
330 SaveUIValues(); 332 SaveUIValues();
333 } else {
334 LOG_DEBUG(Config, "Saving Qt configuration values");
331 } 335 }
332 SaveQtControlValues(); 336 SaveQtControlValues();
333 337
@@ -545,6 +549,7 @@ void QtConfig::ReadQtControlPlayerValues(std::size_t player_index) {
545void QtConfig::SaveQtControlPlayerValues(std::size_t player_index) { 549void QtConfig::SaveQtControlPlayerValues(std::size_t player_index) {
546 BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); 550 BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
547 551
552 LOG_DEBUG(Config, "Saving players control configuration values");
548 SavePlayerValues(player_index); 553 SavePlayerValues(player_index);
549 SaveQtPlayerValues(player_index); 554 SaveQtPlayerValues(player_index);
550 555
diff --git a/src/yuzu_cmd/sdl_config.cpp b/src/yuzu_cmd/sdl_config.cpp
index e81bf5d45..995114510 100644
--- a/src/yuzu_cmd/sdl_config.cpp
+++ b/src/yuzu_cmd/sdl_config.cpp
@@ -5,6 +5,7 @@
5#define SDL_MAIN_HANDLED 5#define SDL_MAIN_HANDLED
6#include <SDL.h> 6#include <SDL.h>
7 7
8#include "common/logging/log.h"
8#include "input_common/main.h" 9#include "input_common/main.h"
9#include "sdl_config.h" 10#include "sdl_config.h"
10 11
@@ -64,7 +65,7 @@ void SdlConfig::ReloadAllValues() {
64} 65}
65 66
66void SdlConfig::SaveAllValues() { 67void SdlConfig::SaveAllValues() {
67 Save(); 68 SaveValues();
68 SaveSdlValues(); 69 SaveSdlValues();
69} 70}
70 71
@@ -177,6 +178,7 @@ void SdlConfig::ReadHidbusValues() {
177} 178}
178 179
179void SdlConfig::SaveSdlValues() { 180void SdlConfig::SaveSdlValues() {
181 LOG_DEBUG(Config, "Saving SDL configuration values");
180 SaveSdlControlValues(); 182 SaveSdlControlValues();
181 183
182 WriteToIni(); 184 WriteToIni();